From 16cc6e9ca2b00a96a226a5f3e6b839cfd10b1b97 Mon Sep 17 00:00:00 2001 From: Christoph Muellner Date: Wed, 22 Apr 2015 15:00:21 +0200 Subject: Revert "android: convert sync to fence api, v6" This reverts commit 0f0d8406fb9c3c5ed1b1609a0f51c504c5b37aea. Conflicts: drivers/staging/android/Makefile drivers/staging/android/sync.c drivers/staging/android/sync_debug.c Signed-off-by: Christoph Muellner --- drivers/staging/android/Kconfig | 1 - drivers/staging/android/Makefile | 2 +- drivers/staging/android/sw_sync.c | 4 +- drivers/staging/android/sync.c | 911 +++++++++++++++++++++++------------ drivers/staging/android/sync.h | 79 ++- drivers/staging/android/sync_debug.c | 254 ---------- drivers/staging/android/trace/sync.h | 12 +- 7 files changed, 648 insertions(+), 615 deletions(-) delete mode 100644 drivers/staging/android/sync_debug.c diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 8feb9048e62f..41f7319f379e 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -32,7 +32,6 @@ 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 diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index c7b6c99cc5ce..2450bd718c66 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile @@ -6,5 +6,5 @@ obj-$(CONFIG_ASHMEM) += ashmem.o obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o -obj-$(CONFIG_SYNC) += sync.o sync_debug.o +obj-$(CONFIG_SYNC) += sync.o obj-$(CONFIG_SW_SYNC) += sw_sync.o diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c index c90838d36953..faa5e239b184 100644 --- a/drivers/staging/android/sw_sync.c +++ b/drivers/staging/android/sw_sync.c @@ -50,7 +50,7 @@ static struct sync_pt *sw_sync_pt_dup(struct sync_pt *sync_pt) { struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt; struct sw_sync_timeline *obj = - (struct sw_sync_timeline *)sync_pt_parent(sync_pt); + (struct sw_sync_timeline *)sync_pt->parent; return (struct sync_pt *)sw_sync_pt_create(obj, pt->value); } @@ -59,7 +59,7 @@ static int sw_sync_pt_has_signaled(struct sync_pt *sync_pt) { struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt; struct sw_sync_timeline *obj = - (struct sw_sync_timeline *)sync_pt_parent(sync_pt); + (struct sw_sync_timeline *)sync_pt->parent; return sw_sync_cmp(obj->value, pt->value) >= 0; } diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 7bdb62bf6b40..cd7b8f59b948 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -31,13 +31,22 @@ #define CREATE_TRACE_POINTS #include "trace/sync.h" -static const struct fence_ops android_fence_ops; -static const struct file_operations sync_fence_fops; +static void sync_fence_signal_pt(struct sync_pt *pt); +static int _sync_pt_has_signaled(struct sync_pt *pt); +static void sync_fence_free(struct kref *kref); +static void sync_dump(void); + +static LIST_HEAD(sync_timeline_list_head); +static DEFINE_SPINLOCK(sync_timeline_list_lock); + +static LIST_HEAD(sync_fence_list_head); +static DEFINE_SPINLOCK(sync_fence_list_lock); struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops, int size, const char *name) { struct sync_timeline *obj; + unsigned long flags; if (size < sizeof(struct sync_timeline)) return NULL; @@ -48,14 +57,17 @@ struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops, kref_init(&obj->kref); obj->ops = ops; - obj->context = fence_context_alloc(1); strlcpy(obj->name, name, sizeof(obj->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); + INIT_LIST_HEAD(&obj->active_list_head); + spin_lock_init(&obj->active_list_lock); + + 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); return obj; } @@ -65,8 +77,11 @@ static void sync_timeline_free(struct kref *kref) { struct sync_timeline *obj = container_of(kref, struct sync_timeline, kref); + unsigned long flags; - sync_timeline_debug_remove(obj); + spin_lock_irqsave(&sync_timeline_list_lock, flags); + list_del(&obj->sync_timeline_list); + spin_unlock_irqrestore(&sync_timeline_list_lock, flags); if (obj->ops->release_obj) obj->ops->release_obj(obj); @@ -74,16 +89,6 @@ static void sync_timeline_free(struct kref *kref) 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; @@ -97,33 +102,75 @@ void sync_timeline_destroy(struct sync_timeline *obj) * signal any children that their parent is going away. */ sync_timeline_signal(obj); - sync_timeline_put(obj); + + kref_put(&obj->kref, sync_timeline_free); } EXPORT_SYMBOL(sync_timeline_destroy); +static void sync_timeline_add_pt(struct sync_timeline *obj, struct sync_pt *pt) +{ + unsigned long flags; + + pt->parent = obj; + + spin_lock_irqsave(&obj->child_list_lock, flags); + list_add_tail(&pt->child_list, &obj->child_list_head); + spin_unlock_irqrestore(&obj->child_list_lock, flags); +} + +static void sync_timeline_remove_pt(struct sync_pt *pt) +{ + struct sync_timeline *obj = pt->parent; + unsigned long flags; + + spin_lock_irqsave(&obj->active_list_lock, flags); + if (!list_empty(&pt->active_list)) + list_del_init(&pt->active_list); + spin_unlock_irqrestore(&obj->active_list_lock, flags); + + spin_lock_irqsave(&obj->child_list_lock, flags); + if (!list_empty(&pt->child_list)) + list_del_init(&pt->child_list); + + spin_unlock_irqrestore(&obj->child_list_lock, flags); +} + void sync_timeline_signal(struct sync_timeline *obj) { unsigned long flags; LIST_HEAD(signaled_pts); - struct sync_pt *pt, *next; + struct list_head *pos, *n; trace_sync_timeline(obj); - spin_lock_irqsave(&obj->child_list_lock, flags); + spin_lock_irqsave(&obj->active_list_lock, flags); + + list_for_each_safe(pos, n, &obj->active_list_head) { + struct sync_pt *pt = + container_of(pos, struct sync_pt, active_list); - list_for_each_entry_safe(pt, next, &obj->active_list_head, - active_list) { - if (fence_is_signaled_locked(&pt->base)) - list_del(&pt->active_list); + if (_sync_pt_has_signaled(pt)) { + list_del_init(pos); + list_add(&pt->signaled_list, &signaled_pts); + kref_get(&pt->fence->kref); + } } - spin_unlock_irqrestore(&obj->child_list_lock, flags); + spin_unlock_irqrestore(&obj->active_list_lock, flags); + + list_for_each_safe(pos, n, &signaled_pts) { + struct sync_pt *pt = + container_of(pos, struct sync_pt, signaled_list); + + list_del_init(pos); + sync_fence_signal_pt(pt); + kref_put(&pt->fence->kref, sync_fence_free); + } } EXPORT_SYMBOL(sync_timeline_signal); -struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size) +struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size) { - unsigned long flags; struct sync_pt *pt; if (size < sizeof(struct sync_pt)) @@ -133,28 +180,87 @@ struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size) if (pt == NULL) return NULL; - spin_lock_irqsave(&obj->child_list_lock, flags); - sync_timeline_get(obj); - fence_init(&pt->base, &android_fence_ops, &obj->child_list_lock, - obj->context, ++obj->value); - list_add_tail(&pt->child_list, &obj->child_list_head); INIT_LIST_HEAD(&pt->active_list); - spin_unlock_irqrestore(&obj->child_list_lock, flags); + kref_get(&parent->kref); + sync_timeline_add_pt(parent, pt); + return pt; } EXPORT_SYMBOL(sync_pt_create); void sync_pt_free(struct sync_pt *pt) { - fence_put(&pt->base); + if (pt->parent->ops->free_pt) + pt->parent->ops->free_pt(pt); + + sync_timeline_remove_pt(pt); + + kref_put(&pt->parent->kref, sync_timeline_free); + + kfree(pt); } EXPORT_SYMBOL(sync_pt_free); -static struct sync_fence *sync_fence_alloc(int size, const char *name) +/* call with pt->parent->active_list_lock held */ +static int _sync_pt_has_signaled(struct sync_pt *pt) +{ + int old_status = pt->status; + + if (!pt->status) + pt->status = pt->parent->ops->has_signaled(pt); + + if (!pt->status && pt->parent->destroyed) + pt->status = -ENOENT; + + if (pt->status != old_status) + pt->timestamp = ktime_get(); + + return pt->status; +} + +static struct sync_pt *sync_pt_dup(struct sync_pt *pt) +{ + return pt->parent->ops->dup(pt); +} + +/* Adds a sync pt to the active queue. Called when added to a fence */ +static void sync_pt_activate(struct sync_pt *pt) +{ + struct sync_timeline *obj = pt->parent; + unsigned long flags; + int err; + + spin_lock_irqsave(&obj->active_list_lock, flags); + + err = _sync_pt_has_signaled(pt); + if (err != 0) + goto out; + + list_add_tail(&pt->active_list, &obj->active_list_head); + +out: + spin_unlock_irqrestore(&obj->active_list_lock, flags); +} + +static int sync_fence_release(struct inode *inode, struct file *file); +static unsigned int sync_fence_poll(struct file *file, poll_table *wait); +static long sync_fence_ioctl(struct file *file, unsigned int cmd, + unsigned long arg); + + +static const struct file_operations sync_fence_fops = { + .release = sync_fence_release, + .poll = sync_fence_poll, + .unlocked_ioctl = sync_fence_ioctl, + .compat_ioctl = sync_fence_ioctl, +}; + +static struct sync_fence *sync_fence_alloc(const char *name) { struct sync_fence *fence; + unsigned long flags; - fence = kzalloc(size, GFP_KERNEL); + fence = kzalloc(sizeof(struct sync_fence), GFP_KERNEL); if (fence == NULL) return NULL; @@ -166,8 +272,16 @@ static struct sync_fence *sync_fence_alloc(int size, const char *name) kref_init(&fence->kref); strlcpy(fence->name, name, sizeof(fence->name)); + INIT_LIST_HEAD(&fence->pt_list_head); + INIT_LIST_HEAD(&fence->waiter_list_head); + spin_lock_init(&fence->waiter_list_lock); + init_waitqueue_head(&fence->wq); + spin_lock_irqsave(&sync_fence_list_lock, flags); + list_add_tail(&fence->sync_fence_list, &sync_fence_list_head); + spin_unlock_irqrestore(&sync_fence_list_lock, flags); + return fence; err: @@ -175,42 +289,121 @@ err: return NULL; } -static void fence_check_cb_func(struct fence *f, struct fence_cb *cb) -{ - struct sync_fence_cb *check; - struct sync_fence *fence; - - check = container_of(cb, struct sync_fence_cb, cb); - fence = check->fence; - - if (atomic_dec_and_test(&fence->status)) - wake_up_all(&fence->wq); -} - /* TODO: implement a create which takes more that one sync_pt */ struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt) { struct sync_fence *fence; - fence = sync_fence_alloc(offsetof(struct sync_fence, cbs[1]), name); - if (fence == NULL) + if (pt->fence) return NULL; - fence->num_fences = 1; - atomic_set(&fence->status, 1); + fence = sync_fence_alloc(name); + if (fence == NULL) + return NULL; - fence->cbs[0].sync_pt = &pt->base; - fence->cbs[0].fence = fence; - if (fence_add_callback(&pt->base, &fence->cbs[0].cb, - fence_check_cb_func)) - atomic_dec(&fence->status); + pt->fence = fence; + list_add(&pt->pt_list, &fence->pt_list_head); + sync_pt_activate(pt); - sync_fence_debug_add(fence); + /* + * signal the fence in case pt was activated before + * sync_pt_activate(pt) was called + */ + sync_fence_signal_pt(pt); return fence; } EXPORT_SYMBOL(sync_fence_create); +static int sync_fence_copy_pts(struct sync_fence *dst, struct sync_fence *src) +{ + struct list_head *pos; + + list_for_each(pos, &src->pt_list_head) { + struct sync_pt *orig_pt = + container_of(pos, struct sync_pt, pt_list); + struct sync_pt *new_pt = sync_pt_dup(orig_pt); + + if (new_pt == NULL) + return -ENOMEM; + + new_pt->fence = dst; + list_add(&new_pt->pt_list, &dst->pt_list_head); + } + + return 0; +} + +static int sync_fence_merge_pts(struct sync_fence *dst, struct sync_fence *src) +{ + struct list_head *src_pos, *dst_pos, *n; + + list_for_each(src_pos, &src->pt_list_head) { + struct sync_pt *src_pt = + container_of(src_pos, struct sync_pt, pt_list); + bool collapsed = false; + + list_for_each_safe(dst_pos, n, &dst->pt_list_head) { + struct sync_pt *dst_pt = + container_of(dst_pos, struct sync_pt, pt_list); + /* collapse two sync_pts on the same timeline + * to a single sync_pt that will signal at + * the later of the two + */ + if (dst_pt->parent == src_pt->parent) { + if (dst_pt->parent->ops->compare(dst_pt, src_pt) + == -1) { + struct sync_pt *new_pt = + sync_pt_dup(src_pt); + if (new_pt == NULL) + return -ENOMEM; + + new_pt->fence = dst; + list_replace(&dst_pt->pt_list, + &new_pt->pt_list); + sync_pt_free(dst_pt); + } + collapsed = true; + break; + } + } + + if (!collapsed) { + struct sync_pt *new_pt = sync_pt_dup(src_pt); + + if (new_pt == NULL) + return -ENOMEM; + + new_pt->fence = dst; + list_add(&new_pt->pt_list, &dst->pt_list_head); + } + } + + return 0; +} + +static void sync_fence_detach_pts(struct sync_fence *fence) +{ + struct list_head *pos, *n; + + list_for_each_safe(pos, n, &fence->pt_list_head) { + struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list); + + sync_timeline_remove_pt(pt); + } +} + +static void sync_fence_free_pts(struct sync_fence *fence) +{ + struct list_head *pos, *n; + + list_for_each_safe(pos, n, &fence->pt_list_head) { + struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list); + + sync_pt_free(pt); + } +} + struct sync_fence *sync_fence_fdget(int fd) { struct file *file = fget(fd); @@ -241,155 +434,197 @@ void sync_fence_install(struct sync_fence *fence, int fd) } EXPORT_SYMBOL(sync_fence_install); -static void sync_fence_add_pt(struct sync_fence *fence, - int *i, struct fence *pt) +static int sync_fence_get_status(struct sync_fence *fence) { - fence->cbs[*i].sync_pt = pt; - fence->cbs[*i].fence = fence; - - if (!fence_add_callback(pt, &fence->cbs[*i].cb, fence_check_cb_func)) { - fence_get(pt); - (*i)++; + struct list_head *pos; + int status = 1; + + list_for_each(pos, &fence->pt_list_head) { + struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list); + int pt_status = pt->status; + + if (pt_status < 0) { + status = pt_status; + break; + } else if (status == 1) { + status = pt_status; + } } + + return status; } struct sync_fence *sync_fence_merge(const char *name, struct sync_fence *a, struct sync_fence *b) { - int num_fences = a->num_fences + b->num_fences; struct sync_fence *fence; - int i, i_a, i_b; - unsigned long size = offsetof(struct sync_fence, cbs[num_fences]); + struct list_head *pos; + int err; - fence = sync_fence_alloc(size, name); + fence = sync_fence_alloc(name); if (fence == NULL) return NULL; - atomic_set(&fence->status, num_fences); - - /* - * Assume sync_fence a and b are both ordered and have no - * duplicates with the same context. - * - * If a sync_fence can only be created with sync_fence_merge - * and sync_fence_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].sync_pt; - struct fence *pt_b = b->cbs[i_b].sync_pt; - - if (pt_a->context < pt_b->context) { - sync_fence_add_pt(fence, &i, pt_a); - - i_a++; - } else if (pt_a->context > pt_b->context) { - sync_fence_add_pt(fence, &i, pt_b); + err = sync_fence_copy_pts(fence, a); + if (err < 0) + goto err; - i_b++; - } else { - if (pt_a->seqno - pt_b->seqno <= INT_MAX) - sync_fence_add_pt(fence, &i, pt_a); - else - sync_fence_add_pt(fence, &i, pt_b); + err = sync_fence_merge_pts(fence, b); + if (err < 0) + goto err; - i_a++; - i_b++; - } + list_for_each(pos, &fence->pt_list_head) { + struct sync_pt *pt = + container_of(pos, struct sync_pt, pt_list); + sync_pt_activate(pt); } - for (; i_a < a->num_fences; i_a++) - sync_fence_add_pt(fence, &i, a->cbs[i_a].sync_pt); - - for (; i_b < b->num_fences; i_b++) - sync_fence_add_pt(fence, &i, b->cbs[i_b].sync_pt); - - if (num_fences > i) - atomic_sub(num_fences - i, &fence->status); - fence->num_fences = i; + /* + * signal the fence in case one of it's pts were activated before + * they were activated + */ + sync_fence_signal_pt(list_first_entry(&fence->pt_list_head, + struct sync_pt, + pt_list)); - sync_fence_debug_add(fence); return fence; +err: + sync_fence_free_pts(fence); + kfree(fence); + return NULL; } EXPORT_SYMBOL(sync_fence_merge); -int sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode, - int wake_flags, void *key) +static void sync_fence_signal_pt(struct sync_pt *pt) { - struct sync_fence_waiter *wait; + LIST_HEAD(signaled_waiters); + struct sync_fence *fence = pt->fence; + struct list_head *pos; + struct list_head *n; + unsigned long flags; + int status; + + status = sync_fence_get_status(fence); + + spin_lock_irqsave(&fence->waiter_list_lock, flags); + /* + * this should protect against two threads racing on the signaled + * false -> true transition + */ + if (status && !fence->status) { + list_for_each_safe(pos, n, &fence->waiter_list_head) + list_move(pos, &signaled_waiters); - wait = container_of(curr, struct sync_fence_waiter, work); - list_del_init(&wait->work.task_list); + fence->status = status; + } else { + status = 0; + } + spin_unlock_irqrestore(&fence->waiter_list_lock, flags); - wait->callback(wait->work.private, wait); - return 1; + if (status) { + list_for_each_safe(pos, n, &signaled_waiters) { + struct sync_fence_waiter *waiter = + container_of(pos, struct sync_fence_waiter, + waiter_list); + + list_del(pos); + waiter->callback(fence, waiter); + } + wake_up(&fence->wq); + } } int sync_fence_wait_async(struct sync_fence *fence, struct sync_fence_waiter *waiter) { - int err = atomic_read(&fence->status); unsigned long flags; + int err = 0; - if (err < 0) - return err; - - if (!err) - return 1; - - init_waitqueue_func_entry(&waiter->work, sync_fence_wake_up_wq); - waiter->work.private = fence; + spin_lock_irqsave(&fence->waiter_list_lock, flags); - spin_lock_irqsave(&fence->wq.lock, flags); - err = atomic_read(&fence->status); - if (err > 0) - __add_wait_queue_tail(&fence->wq, &waiter->work); - spin_unlock_irqrestore(&fence->wq.lock, flags); + if (fence->status) { + err = fence->status; + goto out; + } - if (err < 0) - return err; + list_add_tail(&waiter->waiter_list, &fence->waiter_list_head); +out: + spin_unlock_irqrestore(&fence->waiter_list_lock, flags); - return !err; + return err; } EXPORT_SYMBOL(sync_fence_wait_async); int sync_fence_cancel_async(struct sync_fence *fence, struct sync_fence_waiter *waiter) { + struct list_head *pos; + struct list_head *n; unsigned long flags; - int ret = 0; + int ret = -ENOENT; - spin_lock_irqsave(&fence->wq.lock, flags); - if (!list_empty(&waiter->work.task_list)) - list_del_init(&waiter->work.task_list); - else - ret = -ENOENT; - spin_unlock_irqrestore(&fence->wq.lock, flags); + spin_lock_irqsave(&fence->waiter_list_lock, flags); + /* + * Make sure waiter is still in waiter_list because it is possible for + * the waiter to be removed from the list while the callback is still + * pending. + */ + list_for_each_safe(pos, n, &fence->waiter_list_head) { + struct sync_fence_waiter *list_waiter = + container_of(pos, struct sync_fence_waiter, + waiter_list); + if (list_waiter == waiter) { + list_del(pos); + ret = 0; + break; + } + } + spin_unlock_irqrestore(&fence->waiter_list_lock, flags); return ret; } EXPORT_SYMBOL(sync_fence_cancel_async); -int sync_fence_wait(struct sync_fence *fence, long timeout) +static bool sync_fence_check(struct sync_fence *fence) { - long ret; - int i; + /* + * Make sure that reads to fence->status are ordered with the + * wait queue event triggering + */ + smp_rmb(); + return fence->status != 0; +} - if (timeout < 0) - timeout = MAX_SCHEDULE_TIMEOUT; - else - timeout = msecs_to_jiffies(timeout); +int sync_fence_wait(struct sync_fence *fence, long timeout) +{ + int err = 0; + struct sync_pt *pt; trace_sync_wait(fence, 1); - for (i = 0; i < fence->num_fences; ++i) - trace_sync_pt(fence->cbs[i].sync_pt); - ret = wait_event_interruptible_timeout(fence->wq, - atomic_read(&fence->status) <= 0, - timeout); + list_for_each_entry(pt, &fence->pt_list_head, pt_list) + trace_sync_pt(pt); + + if (timeout > 0) { + timeout = msecs_to_jiffies(timeout); + err = wait_event_interruptible_timeout(fence->wq, + sync_fence_check(fence), + timeout); + } else if (timeout < 0) { + err = wait_event_interruptible(fence->wq, + sync_fence_check(fence)); + } trace_sync_wait(fence, 0); - if (ret < 0) { - return ret; - } else if (ret == 0) { - if (timeout) { + if (err < 0) + return err; + + if (fence->status < 0) { + pr_info("fence error %d on [%p]\n", fence->status, fence); + sync_dump(); + return fence->status; + } + + if (fence->status == 0) { + if (timeout > 0) { pr_info("fence timeout on [%p] after %dms\n", fence, jiffies_to_msecs(timeout)); sync_dump(); @@ -397,136 +632,15 @@ int sync_fence_wait(struct sync_fence *fence, long timeout) return -ETIME; } - ret = atomic_read(&fence->status); - if (ret) { - pr_info("fence error %ld on [%p]\n", ret, fence); - sync_dump(); - } - return ret; + return 0; } EXPORT_SYMBOL(sync_fence_wait); -static const char *android_fence_get_driver_name(struct fence *fence) -{ - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); - - return parent->ops->driver_name; -} - -static const char *android_fence_get_timeline_name(struct fence *fence) -{ - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); - - return parent->name; -} - -static void android_fence_release(struct fence *fence) -{ - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); - unsigned long flags; - - spin_lock_irqsave(fence->lock, flags); - list_del(&pt->child_list); - if (WARN_ON_ONCE(!list_empty(&pt->active_list))) - list_del(&pt->active_list); - spin_unlock_irqrestore(fence->lock, flags); - - if (parent->ops->free_pt) - parent->ops->free_pt(pt); - - sync_timeline_put(parent); - fence_free(&pt->base); -} - -static bool android_fence_signaled(struct fence *fence) -{ - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); - int ret; - - ret = parent->ops->has_signaled(pt); - if (ret < 0) - fence->status = ret; - return ret; -} - -static bool android_fence_enable_signaling(struct fence *fence) -{ - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); - - if (android_fence_signaled(fence)) - return false; - - list_add_tail(&pt->active_list, &parent->active_list_head); - return true; -} - -static int android_fence_fill_driver_data(struct fence *fence, - void *data, int size) -{ - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); - - if (!parent->ops->fill_driver_data) - return 0; - return parent->ops->fill_driver_data(pt, data, size); -} - -static void android_fence_value_str(struct fence *fence, - char *str, int size) -{ - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); - - if (!parent->ops->pt_value_str) { - if (size) - *str = 0; - return; - } - parent->ops->pt_value_str(pt, str, size); -} - -static void android_fence_timeline_value_str(struct fence *fence, - char *str, int size) -{ - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); - - if (!parent->ops->timeline_value_str) { - if (size) - *str = 0; - return; - } - parent->ops->timeline_value_str(parent, str, size); -} - -static const struct fence_ops android_fence_ops = { - .get_driver_name = android_fence_get_driver_name, - .get_timeline_name = android_fence_get_timeline_name, - .enable_signaling = android_fence_enable_signaling, - .signaled = android_fence_signaled, - .wait = fence_default_wait, - .release = android_fence_release, - .fill_driver_data = android_fence_fill_driver_data, - .fence_value_str = android_fence_value_str, - .timeline_value_str = android_fence_timeline_value_str, -}; - static void sync_fence_free(struct kref *kref) { struct sync_fence *fence = container_of(kref, struct sync_fence, kref); - int i, status = atomic_read(&fence->status); - for (i = 0; i < fence->num_fences; ++i) { - if (status) - fence_remove_callback(fence->cbs[i].sync_pt, - &fence->cbs[i].cb); - fence_put(fence->cbs[i].sync_pt); - } + sync_fence_free_pts(fence); kfree(fence); } @@ -534,25 +648,44 @@ static void sync_fence_free(struct kref *kref) static int sync_fence_release(struct inode *inode, struct file *file) { struct sync_fence *fence = file->private_data; + unsigned long flags; + + /* + * We need to remove all ways to access this fence before droping + * our ref. + * + * start with its membership in the global fence list + */ + spin_lock_irqsave(&sync_fence_list_lock, flags); + list_del(&fence->sync_fence_list); + spin_unlock_irqrestore(&sync_fence_list_lock, flags); - sync_fence_debug_remove(fence); + /* + * remove its pts from their parents so that sync_timeline_signal() + * can't reference the fence. + */ + sync_fence_detach_pts(fence); kref_put(&fence->kref, sync_fence_free); + return 0; } static unsigned int sync_fence_poll(struct file *file, poll_table *wait) { struct sync_fence *fence = file->private_data; - int status; poll_wait(file, &fence->wq, wait); - status = atomic_read(&fence->status); + /* + * Make sure that reads to fence->status are ordered with the + * wait queue event triggering + */ + smp_rmb(); - if (!status) + if (fence->status == 1) return POLLIN; - else if (status < 0) + else if (fence->status < 0) return POLLERR; return 0; } @@ -616,7 +749,7 @@ err_put_fd: return err; } -static int sync_fill_pt_info(struct fence *fence, void *data, int size) +static int sync_fill_pt_info(struct sync_pt *pt, void *data, int size) { struct sync_pt_info *info = data; int ret; @@ -626,24 +759,20 @@ static int sync_fill_pt_info(struct fence *fence, void *data, int size) 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 (pt->parent->ops->fill_driver_data) { + ret = pt->parent->ops->fill_driver_data(pt, 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), + strlcpy(info->obj_name, pt->parent->name, sizeof(info->obj_name)); + strlcpy(info->driver_name, pt->parent->ops->driver_name, 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); + info->status = pt->status; + info->timestamp_ns = ktime_to_ns(pt->timestamp); return info->len; } @@ -652,9 +781,10 @@ static long sync_fence_ioctl_fence_info(struct sync_fence *fence, unsigned long arg) { struct sync_fence_info_data *data; + struct list_head *pos; __u32 size; __u32 len = 0; - int ret, i; + int ret; if (copy_from_user(&size, (void __user *)arg, sizeof(size))) return -EFAULT; @@ -670,14 +800,12 @@ static long sync_fence_ioctl_fence_info(struct sync_fence *fence, return -ENOMEM; strlcpy(data->name, fence->name, sizeof(data->name)); - data->status = atomic_read(&fence->status); - if (data->status >= 0) - data->status = !data->status; - + data->status = fence->status; len = sizeof(struct sync_fence_info_data); - for (i = 0; i < fence->num_fences; ++i) { - struct fence *pt = fence->cbs[i].sync_pt; + list_for_each(pos, &fence->pt_list_head) { + struct sync_pt *pt = + container_of(pos, struct sync_pt, pt_list); ret = sync_fill_pt_info(pt, (u8 *)data + len, size - len); @@ -720,10 +848,181 @@ static long sync_fence_ioctl(struct file *file, unsigned int cmd, } } -static const struct file_operations sync_fence_fops = { - .release = sync_fence_release, - .poll = sync_fence_poll, - .unlocked_ioctl = sync_fence_ioctl, - .compat_ioctl = sync_fence_ioctl, +#ifdef CONFIG_DEBUG_FS +static const char *sync_status_str(int status) +{ + if (status > 0) + return "signaled"; + else if (status == 0) + return "active"; + else + return "error"; +} + +static void sync_print_pt(struct seq_file *s, struct sync_pt *pt, bool fence) +{ + int status = pt->status; + + seq_printf(s, " %s%spt %s", + fence ? pt->parent->name : "", + fence ? "_" : "", + sync_status_str(status)); + if (pt->status) { + struct timeval tv = ktime_to_timeval(pt->timestamp); + + seq_printf(s, "@%ld.%06ld", tv.tv_sec, tv.tv_usec); + } + + if (pt->parent->ops->timeline_value_str && + pt->parent->ops->pt_value_str) { + char value[64]; + + pt->parent->ops->pt_value_str(pt, value, sizeof(value)); + seq_printf(s, ": %s", value); + if (fence) { + pt->parent->ops->timeline_value_str(pt->parent, value, + sizeof(value)); + seq_printf(s, " / %s", value); + } + } else if (pt->parent->ops->print_pt) { + seq_puts(s, ": "); + pt->parent->ops->print_pt(s, pt); + } + + 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", obj->name, obj->ops->driver_name); + + if (obj->ops->timeline_value_str) { + char value[64]; + + obj->ops->timeline_value_str(obj, value, sizeof(value)); + seq_printf(s, ": %s", value); + } else if (obj->ops->print_obj) { + seq_puts(s, ": "); + obj->ops->print_obj(s, obj); + } + + seq_puts(s, "\n"); + + spin_lock_irqsave(&obj->child_list_lock, flags); + list_for_each(pos, &obj->child_list_head) { + struct sync_pt *pt = + container_of(pos, struct sync_pt, child_list); + sync_print_pt(s, pt, false); + } + spin_unlock_irqrestore(&obj->child_list_lock, flags); +} + +static void sync_print_fence(struct seq_file *s, struct sync_fence *fence) +{ + struct list_head *pos; + unsigned long flags; + + seq_printf(s, "[%p] %s: %s\n", fence, fence->name, + sync_status_str(fence->status)); + + list_for_each(pos, &fence->pt_list_head) { + struct sync_pt *pt = + container_of(pos, struct sync_pt, pt_list); + sync_print_pt(s, pt, true); + } + + spin_lock_irqsave(&fence->waiter_list_lock, flags); + list_for_each(pos, &fence->waiter_list_head) { + struct sync_fence_waiter *waiter = + container_of(pos, struct sync_fence_waiter, + waiter_list); + + seq_printf(s, "waiter %pF\n", waiter->callback); + } + spin_unlock_irqrestore(&fence->waiter_list_lock, flags); +} + +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_fence_list_lock, flags); + list_for_each(pos, &sync_fence_list_head) { + struct sync_fence *fence = + container_of(pos, struct sync_fence, sync_fence_list); + + sync_print_fence(s, fence); + seq_puts(s, "\n"); + } + spin_unlock_irqrestore(&sync_fence_list_lock, flags); + return 0; +} + +static int sync_debugfs_open(struct inode *inode, struct file *file) +{ + return single_open(file, sync_debugfs_show, inode->i_private); +} + +static const struct file_operations sync_debugfs_fops = { + .open = sync_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, }; +static __init int sync_debugfs_init(void) +{ + debugfs_create_file("sync", S_IRUGO, NULL, NULL, &sync_debugfs_fops); + return 0; +} +late_initcall(sync_debugfs_init); + +#define DUMP_CHUNK 256 +static char sync_dump_buf[64 * 1024]; +static 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); + } + } +} +#else +static void sync_dump(void) +{ +} +#endif diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index a21b79fb4c8e..9babc0add723 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -19,7 +19,6 @@ #include #include #include -#include #include "uapi/sync.h" @@ -41,6 +40,8 @@ struct sync_fence; * -1 if a will signal before b * @free_pt: called before sync_pt is freed * @release_obj: called before sync_timeline is freed + * @print_obj: deprecated + * @print_pt: deprecated * @fill_driver_data: write implementation specific driver data to data. * should return an error if there is not enough room * as specified by size. This information is returned @@ -66,6 +67,13 @@ struct sync_timeline_ops { /* optional */ void (*release_obj)(struct sync_timeline *sync_timeline); + /* deprecated */ + void (*print_obj)(struct seq_file *s, + struct sync_timeline *sync_timeline); + + /* deprecated */ + void (*print_pt)(struct seq_file *s, struct sync_pt *sync_pt); + /* optional */ int (*fill_driver_data)(struct sync_pt *syncpt, void *data, int size); @@ -96,21 +104,19 @@ struct sync_timeline { /* 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; + spinlock_t active_list_lock; -#ifdef CONFIG_DEBUG_FS struct list_head sync_timeline_list; -#endif }; /** * struct sync_pt - sync point - * @fence: base fence class + * @parent: sync_timeline to which this sync_pt belongs * @child_list: membership in sync_timeline.child_list_head * @active_list: membership in sync_timeline.active_list_head * @signaled_list: membership in temporary signaled_list on stack @@ -121,22 +127,19 @@ struct sync_timeline { * signaled or error. */ struct sync_pt { - struct fence base; - + struct sync_timeline *parent; struct list_head child_list; + struct list_head active_list; -}; + struct list_head signaled_list; -static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt) -{ - return container_of(pt->base.lock, struct sync_timeline, - child_list_lock); -} + struct sync_fence *fence; + struct list_head pt_list; + + /* protected by parent->active_list_lock */ + int status; -struct sync_fence_cb { - struct fence_cb cb; - struct fence *sync_pt; - struct sync_fence *fence; + ktime_t timestamp; }; /** @@ -146,7 +149,9 @@ struct sync_fence_cb { * @name: name of sync_fence. Useful for debugging * @pt_list_head: list of sync_pts in the fence. immutable once fence * is created - * @status: 0: signaled, >0:active, <0: error + * @waiter_list_head: list of asynchronous waiters on this fence + * @waiter_list_lock: lock protecting @waiter_list_head and @status + * @status: 1: signaled, 0:active, <0: error * * @wq: wait queue for fence signaling * @sync_fence_list: membership in global fence list @@ -155,15 +160,17 @@ struct sync_fence { struct file *file; struct kref kref; char name[32]; -#ifdef CONFIG_DEBUG_FS - struct list_head sync_fence_list; -#endif - int num_fences; + + /* this list is immutable once the fence is created */ + struct list_head pt_list_head; + + struct list_head waiter_list_head; + spinlock_t waiter_list_lock; /* also protects status */ + int status; wait_queue_head_t wq; - atomic_t status; - struct sync_fence_cb cbs[]; + struct list_head sync_fence_list; }; struct sync_fence_waiter; @@ -177,14 +184,14 @@ typedef void (*sync_callback_t)(struct sync_fence *fence, * @callback_data: pointer to pass to @callback */ struct sync_fence_waiter { - wait_queue_t work; - sync_callback_t callback; + struct list_head waiter_list; + + sync_callback_t callback; }; static inline void sync_fence_waiter_init(struct sync_fence_waiter *waiter, sync_callback_t callback) { - INIT_LIST_HEAD(&waiter->work.task_list); waiter->callback = callback; } @@ -335,22 +342,4 @@ int sync_fence_cancel_async(struct sync_fence *fence, */ int sync_fence_wait(struct sync_fence *fence, long timeout); -#ifdef CONFIG_DEBUG_FS - -extern void sync_timeline_debug_add(struct sync_timeline *obj); -extern void sync_timeline_debug_remove(struct sync_timeline *obj); -extern void sync_fence_debug_add(struct sync_fence *fence); -extern void sync_fence_debug_remove(struct sync_fence *fence); -extern void sync_dump(void); - -#else -# define sync_timeline_debug_add(obj) -# define sync_timeline_debug_remove(obj) -# define sync_fence_debug_add(fence) -# define sync_fence_debug_remove(fence) -# define sync_dump() -#endif -int sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode, - int wake_flags, void *key); - #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 91ed2c4cff45..000000000000 --- a/drivers/staging/android/sync_debug.c +++ /dev/null @@ -1,254 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sync.h" - -#ifdef CONFIG_DEBUG_FS - -static LIST_HEAD(sync_timeline_list_head); -static DEFINE_SPINLOCK(sync_timeline_list_lock); -static LIST_HEAD(sync_fence_list_head); -static DEFINE_SPINLOCK(sync_fence_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_fence_debug_add(struct sync_fence *fence) -{ - unsigned long flags; - - spin_lock_irqsave(&sync_fence_list_lock, flags); - list_add_tail(&fence->sync_fence_list, &sync_fence_list_head); - spin_unlock_irqrestore(&sync_fence_list_lock, flags); -} - -void sync_fence_debug_remove(struct sync_fence *fence) -{ - unsigned long flags; - - spin_lock_irqsave(&sync_fence_list_lock, flags); - list_del(&fence->sync_fence_list); - spin_unlock_irqrestore(&sync_fence_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_pt(struct seq_file *s, struct sync_pt *pt, bool fence) -{ - int status = 1; - struct sync_timeline *parent = sync_pt_parent(pt); - - if (fence_is_signaled_locked(&pt->base)) - status = pt->base.status; - - seq_printf(s, " %s%spt %s", - fence ? parent->name : "", - fence ? "_" : "", - sync_status_str(status)); - - if (status <= 0) { - struct timespec64 ts64 = - ktime_to_timespec64(pt->base.timestamp); - - seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec); - } - - if (parent->ops->timeline_value_str && - parent->ops->pt_value_str) { - char value[64]; - - parent->ops->pt_value_str(pt, value, sizeof(value)); - seq_printf(s, ": %s", value); - if (fence) { - parent->ops->timeline_value_str(parent, value, - sizeof(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", obj->name, obj->ops->driver_name); - - if (obj->ops->timeline_value_str) { - char value[64]; - - obj->ops->timeline_value_str(obj, value, sizeof(value)); - seq_printf(s, ": %s", value); - } - - seq_puts(s, "\n"); - - spin_lock_irqsave(&obj->child_list_lock, flags); - list_for_each(pos, &obj->child_list_head) { - struct sync_pt *pt = - container_of(pos, struct sync_pt, child_list); - sync_print_pt(s, pt, false); - } - spin_unlock_irqrestore(&obj->child_list_lock, flags); -} - -static void sync_print_fence(struct seq_file *s, struct sync_fence *fence) -{ - wait_queue_t *pos; - unsigned long flags; - int i; - - seq_printf(s, "[%p] %s: %s\n", fence, fence->name, - sync_status_str(atomic_read(&fence->status))); - - for (i = 0; i < fence->num_fences; ++i) { - struct sync_pt *pt = - container_of(fence->cbs[i].sync_pt, - struct sync_pt, base); - - sync_print_pt(s, pt, true); - } - - spin_lock_irqsave(&fence->wq.lock, flags); - list_for_each_entry(pos, &fence->wq.task_list, task_list) { - struct sync_fence_waiter *waiter; - - if (pos->func != &sync_fence_wake_up_wq) - continue; - - waiter = container_of(pos, struct sync_fence_waiter, work); - - seq_printf(s, "waiter %pF\n", waiter->callback); - } - spin_unlock_irqrestore(&fence->wq.lock, flags); -} - -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_fence_list_lock, flags); - list_for_each(pos, &sync_fence_list_head) { - struct sync_fence *fence = - container_of(pos, struct sync_fence, sync_fence_list); - - sync_print_fence(s, fence); - seq_puts(s, "\n"); - } - spin_unlock_irqrestore(&sync_fence_list_lock, flags); - return 0; -} - -static int sync_debugfs_open(struct inode *inode, struct file *file) -{ - return single_open(file, sync_debugfs_show, inode->i_private); -} - -static const struct file_operations sync_debugfs_fops = { - .open = sync_debugfs_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static __init int sync_debugfs_init(void) -{ - debugfs_create_file("sync", S_IRUGO, NULL, NULL, &sync_debugfs_fops); - return 0; -} -late_initcall(sync_debugfs_init); - -#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 index 77edb977a7bf..95462359ba57 100644 --- a/drivers/staging/android/trace/sync.h +++ b/drivers/staging/android/trace/sync.h @@ -45,7 +45,7 @@ TRACE_EVENT(sync_wait, TP_fast_assign( __assign_str(name, fence->name); - __entry->status = atomic_read(&fence->status); + __entry->status = fence->status; __entry->begin = begin; ), @@ -54,19 +54,19 @@ TRACE_EVENT(sync_wait, ); TRACE_EVENT(sync_pt, - TP_PROTO(struct fence *pt), + TP_PROTO(struct sync_pt *pt), TP_ARGS(pt), TP_STRUCT__entry( - __string(timeline, pt->ops->get_timeline_name(pt)) + __string(timeline, pt->parent->name) __array(char, value, 32) ), TP_fast_assign( - __assign_str(timeline, pt->ops->get_timeline_name(pt)); - if (pt->ops->fence_value_str) { - pt->ops->fence_value_str(pt, __entry->value, + __assign_str(timeline, pt->parent->name); + if (pt->parent->ops->pt_value_str) { + pt->parent->ops->pt_value_str(pt, __entry->value, sizeof(__entry->value)); } else { __entry->value[0] = '\0'; -- cgit v1.2.3