From e8f89ae535e227490d3116a03f2be5dc780e5be9 Mon Sep 17 00:00:00 2001
From: Colin Cross <ccross@android.com>
Date: Fri, 1 Nov 2013 19:26:54 -0700
Subject: [PATCH] dma fence fixes

Change-Id: I9308b51c23e762fde95106db301cf6aedd8845f5
---
 drivers/staging/android/sync.c       | 27 +++++++++++++++++++++------
 drivers/staging/android/sync_debug.c | 10 ++++------
 include/linux/fence.h                |  4 ++--
 3 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c
index 110a9e99cb71..672020d5f566 100644
--- a/drivers/staging/android/sync.c
+++ b/drivers/staging/android/sync.c
@@ -74,6 +74,16 @@ 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;
@@ -83,8 +93,8 @@ void sync_timeline_destroy(struct sync_timeline *obj)
 	 * that their parent is going away.
 	 */
 
-	if (!kref_put(&obj->kref, sync_timeline_free))
-		sync_timeline_signal(obj);
+	sync_timeline_signal(obj);
+	sync_timeline_put(obj);
 }
 EXPORT_SYMBOL(sync_timeline_destroy);
 
@@ -98,9 +108,7 @@ void sync_timeline_signal(struct sync_timeline *obj)
 
 	spin_lock_irqsave(&obj->child_list_lock, flags);
 	list_for_each_entry_safe(pt, next, &obj->active_list_head, active_list) {
-		if (!pt->base.ops->signaled(&pt->base))
-			break;
-		else {
+		if (pt->base.ops->signaled(&pt->base)) {
 			__fence_signal(&pt->base);
 			list_del(&pt->active_list);
 		}
@@ -122,6 +130,7 @@ struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size)
 		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);
@@ -186,6 +195,7 @@ struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt)
 	fence_get(&pt->base);
 	fence->cbs[0].sync_pt = &pt->base;
 	fence->cbs[0].fence = fence;
+	INIT_LIST_HEAD(&fence->cbs[0].cb.node);
 	if (fence_add_callback(&pt->base, &fence->cbs[0].cb, fence_check_cb_func))
 		atomic_dec(&fence->status);
 
@@ -245,6 +255,7 @@ struct sync_fence *sync_fence_merge(const char *name,
 		fence_get(pt);
 		fence->cbs[i].sync_pt = pt;
 		fence->cbs[i].fence = fence;
+		INIT_LIST_HEAD(&fence->cbs[i].cb.node);
 		if (fence_add_callback(pt, &fence->cbs[i].cb, fence_check_cb_func))
 			atomic_dec(&fence->status);
 	}
@@ -255,7 +266,8 @@ struct sync_fence *sync_fence_merge(const char *name,
 		fence_get(pt);
 		fence->cbs[a->num_fences + i].sync_pt = pt;
 		fence->cbs[a->num_fences + i].fence = fence;
-		if (fence_add_callback(pt, &fence->cbs[i].cb, fence_check_cb_func))
+		INIT_LIST_HEAD(&fence->cbs[a->num_fences + i].cb.node);
+		if (fence_add_callback(pt, &fence->cbs[a->num_fences + i].cb, fence_check_cb_func))
 			atomic_dec(&fence->status);
 	}
 
@@ -325,6 +337,8 @@ int sync_fence_wait(struct sync_fence *fence, long timeout)
 
 	if (timeout < 0)
 		timeout = MAX_SCHEDULE_TIMEOUT;
+	else
+		timeout = msecs_to_jiffies(timeout);
 
 	trace_sync_wait(fence, 1);
 	for (i = 0; i < fence->num_fences; ++i)
@@ -383,6 +397,7 @@ static void android_fence_release(struct fence *fence)
 	if (parent->ops->free_pt)
 		parent->ops->free_pt(pt);
 
+	sync_timeline_put(parent);
 	kfree(pt);
 }
 
diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c
index 55ad34085f2f..8671fbb7d143 100644
--- a/drivers/staging/android/sync_debug.c
+++ b/drivers/staging/android/sync_debug.c
@@ -82,18 +82,16 @@ static const char *sync_status_str(int status)
 
 static void sync_print_pt(struct seq_file *s, struct sync_pt *pt, bool fence)
 {
-	int status = 0;
+	int status = 1;
 	struct sync_timeline *parent = sync_pt_parent(pt);
-	if (fence_is_signaled(&pt->base)) {
+	if (fence_is_signaled(&pt->base))
 		status = pt->base.status;
-		if (!status)
-			status = 1;
-	}
+
 	seq_printf(s, "  %s%spt %s",
 		   fence ? parent->name : "",
 		   fence ? "_" : "",
 		   sync_status_str(status));
-	if (status) {
+	if (!status) {
 		struct timeval tv = ktime_to_timeval(pt->base.timestamp);
 		seq_printf(s, "@%ld.%06ld", tv.tv_sec, tv.tv_usec);
 	}
diff --git a/include/linux/fence.h b/include/linux/fence.h
index 2beb3b0ff2a3..e1b2fc6e8007 100644
--- a/include/linux/fence.h
+++ b/include/linux/fence.h
@@ -257,10 +257,10 @@ fence_is_signaled(struct fence *fence)
 	if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
 		return true;
 
-	if (fence->ops->signaled && fence->ops->signaled(fence)) {
+	/*if (fence->ops->signaled && fence->ops->signaled(fence)) {
 		fence_signal(fence);
 		return true;
-	}
+	}*/
 
 	return false;
 }
-- 
1.8.4.1
