--- /dev/null
+From 8111477663813caa1a4469cfe6afaae36cd04513 Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Thu, 29 Jun 2017 13:59:24 +0100
+Subject: dma-buf/dma-fence: Extract __dma_fence_is_later()
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 8111477663813caa1a4469cfe6afaae36cd04513 upstream.
+
+Often we have the task of comparing two seqno known to be on the same
+context, so provide a common __dma_fence_is_later().
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Cc: Sumit Semwal <sumit.semwal@linaro.org>
+Cc: Sean Paul <seanpaul@chromium.org>
+Cc: Gustavo Padovan <gustavo@padovan.org>
+Reviewed-by: Sean Paul <seanpaul@chromium.org>
+Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
+Link: http://patchwork.freedesktop.org/patch/msgid/20170629125930.821-1-chris@chris-wilson.co.uk
+[renamed to __fence_is_later() - gregkh]
+Cc: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/fence.h | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+--- a/include/linux/fence.h
++++ b/include/linux/fence.h
+@@ -281,6 +281,19 @@ fence_is_signaled(struct fence *fence)
+ }
+
+ /**
++ * __fence_is_later - return if f1 is chronologically later than f2
++ * @f1: [in] the first fence's seqno
++ * @f2: [in] the second fence's seqno from the same context
++ *
++ * Returns true if f1 is chronologically later than f2. Both fences must be
++ * from the same context, since a seqno is not common across contexts.
++ */
++static inline bool __fence_is_later(u32 f1, u32 f2)
++{
++ return (int)(f1 - f2) > 0;
++}
++
++/**
+ * fence_is_later - return if f1 is chronologically later than f2
+ * @f1: [in] the first fence from the same context
+ * @f2: [in] the second fence from the same context
+@@ -293,7 +306,7 @@ static inline bool fence_is_later(struct
+ if (WARN_ON(f1->context != f2->context))
+ return false;
+
+- return (int)(f1->seqno - f2->seqno) > 0;
++ return __fence_is_later(f1->seqno, f2->seqno);
+ }
+
+ /**
--- /dev/null
+From d3862e44daa7a0c94d2f6193502a8c49379acfce Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Thu, 29 Jun 2017 22:05:32 +0100
+Subject: dma-buf/sw-sync: Fix locking around sync_timeline lists
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit d3862e44daa7a0c94d2f6193502a8c49379acfce upstream.
+
+The sync_pt were not adding themselves atomically to the timeline lists,
+corruption imminent. Only a single list is required to track the
+unsignaled sync_pt, so reduce it and rename the lock more appropriately
+along with using idiomatic names to distinguish a list from links along
+it.
+
+v2: Prevent spinlock recursion on free during create (next patch) and
+fixup crossref in kerneldoc
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Cc: Sumit Semwal <sumit.semwal@linaro.org>
+Cc: Sean Paul <seanpaul@chromium.org>
+Cc: Gustavo Padovan <gustavo@padovan.org>
+Reviewed-by: Sean Paul <seanpaul@chromium.org>
+Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
+Link: http://patchwork.freedesktop.org/patch/msgid/20170629210532.5617-1-chris@chris-wilson.co.uk
+[s/dma_fence/fence/g - gregkh]
+Cc: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma-buf/sw_sync.c | 48 +++++++++++++++++--------------------------
+ drivers/dma-buf/sync_debug.c | 9 +++-----
+ drivers/dma-buf/sync_debug.h | 22 +++++++------------
+ 3 files changed, 31 insertions(+), 48 deletions(-)
+
+--- a/drivers/dma-buf/sw_sync.c
++++ b/drivers/dma-buf/sw_sync.c
+@@ -96,9 +96,8 @@ struct sync_timeline *sync_timeline_crea
+ 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);
++ INIT_LIST_HEAD(&obj->pt_list);
++ spin_lock_init(&obj->lock);
+
+ sync_timeline_debug_add(obj);
+
+@@ -139,17 +138,15 @@ static void sync_timeline_signal(struct
+
+ trace_sync_timeline(obj);
+
+- spin_lock_irq(&obj->child_list_lock);
++ spin_lock_irq(&obj->lock);
+
+ obj->value += inc;
+
+- list_for_each_entry_safe(pt, next, &obj->active_list_head,
+- active_list) {
++ list_for_each_entry_safe(pt, next, &obj->pt_list, link)
+ if (fence_is_signaled_locked(&pt->base))
+- list_del_init(&pt->active_list);
+- }
++ list_del_init(&pt->link);
+
+- spin_unlock_irq(&obj->child_list_lock);
++ spin_unlock_irq(&obj->lock);
+ }
+
+ /**
+@@ -171,15 +168,15 @@ static struct sync_pt *sync_pt_create(st
+ if (!pt)
+ return NULL;
+
+- spin_lock_irq(&obj->child_list_lock);
+-
+ sync_timeline_get(obj);
+- fence_init(&pt->base, &timeline_fence_ops, &obj->child_list_lock,
++ fence_init(&pt->base, &timeline_fence_ops, &obj->lock,
+ obj->context, value);
+- list_add_tail(&pt->child_list, &obj->child_list_head);
+- INIT_LIST_HEAD(&pt->active_list);
++ INIT_LIST_HEAD(&pt->link);
+
+- spin_unlock_irq(&obj->child_list_lock);
++ spin_lock_irq(&obj->lock);
++ if (!fence_is_signaled_locked(&pt->base))
++ list_add_tail(&pt->link, &obj->pt_list);
++ spin_unlock_irq(&obj->lock);
+
+ return pt;
+ }
+@@ -200,15 +197,15 @@ static void timeline_fence_release(struc
+ {
+ struct sync_pt *pt = fence_to_sync_pt(fence);
+ struct sync_timeline *parent = fence_parent(fence);
+- unsigned long flags;
+
+- spin_lock_irqsave(fence->lock, flags);
++ if (!list_empty(&pt->link)) {
++ unsigned long flags;
+
+- list_del(&pt->child_list);
+- if (!list_empty(&pt->active_list))
+- list_del(&pt->active_list);
+-
+- spin_unlock_irqrestore(fence->lock, flags);
++ spin_lock_irqsave(fence->lock, flags);
++ if (!list_empty(&pt->link))
++ list_del(&pt->link);
++ spin_unlock_irqrestore(fence->lock, flags);
++ }
+
+ sync_timeline_put(parent);
+ fence_free(fence);
+@@ -223,13 +220,6 @@ static bool timeline_fence_signaled(stru
+
+ static bool timeline_fence_enable_signaling(struct fence *fence)
+ {
+- struct sync_pt *pt = fence_to_sync_pt(fence);
+- struct sync_timeline *parent = fence_parent(fence);
+-
+- if (timeline_fence_signaled(fence))
+- return false;
+-
+- list_add_tail(&pt->active_list, &parent->active_list_head);
+ return true;
+ }
+
+--- a/drivers/dma-buf/sync_debug.c
++++ b/drivers/dma-buf/sync_debug.c
+@@ -119,13 +119,12 @@ static void sync_print_obj(struct seq_fi
+
+ seq_printf(s, "%s: %d\n", obj->name, obj->value);
+
+- spin_lock_irq(&obj->child_list_lock);
+- list_for_each(pos, &obj->child_list_head) {
+- struct sync_pt *pt =
+- container_of(pos, struct sync_pt, child_list);
++ spin_lock_irq(&obj->lock);
++ list_for_each(pos, &obj->pt_list) {
++ struct sync_pt *pt = container_of(pos, struct sync_pt, link);
+ sync_print_fence(s, &pt->base, false);
+ }
+- spin_unlock_irq(&obj->child_list_lock);
++ spin_unlock_irq(&obj->lock);
+ }
+
+ static void sync_print_sync_file(struct seq_file *s,
+--- a/drivers/dma-buf/sync_debug.h
++++ b/drivers/dma-buf/sync_debug.h
+@@ -24,43 +24,37 @@
+ * struct sync_timeline - sync object
+ * @kref: reference count on fence.
+ * @name: name of the sync_timeline. Useful for debugging
+- * @child_list_head: list of children sync_pts for this sync_timeline
+- * @child_list_lock: lock protecting @child_list_head and fence.status
+- * @active_list_head: list of active (unsignaled/errored) sync_pts
++ * @lock: lock protecting @pt_list and @value
++ * @pt_list: list of active (unsignaled/errored) sync_pts
+ * @sync_timeline_list: membership in global sync_timeline_list
+ */
+ struct sync_timeline {
+ struct kref kref;
+ char name[32];
+
+- /* protected by child_list_lock */
++ /* protected by lock */
+ u64 context;
+ int value;
+
+- struct list_head child_list_head;
+- spinlock_t child_list_lock;
+-
+- struct list_head active_list_head;
++ struct list_head pt_list;
++ spinlock_t lock;
+
+ struct list_head sync_timeline_list;
+ };
+
+ static inline struct sync_timeline *fence_parent(struct fence *fence)
+ {
+- return container_of(fence->lock, struct sync_timeline,
+- child_list_lock);
++ return container_of(fence->lock, struct sync_timeline, lock);
+ }
+
+ /**
+ * struct sync_pt - sync_pt object
+ * @base: base fence object
+- * @child_list: sync timeline child's list
+- * @active_list: sync timeline active child's list
++ * @link: link on the sync timeline's list
+ */
+ struct sync_pt {
+ struct fence base;
+- struct list_head child_list;
+- struct list_head active_list;
++ struct list_head link;
+ };
+
+ #ifdef CONFIG_SW_SYNC
--- /dev/null
+From 61894b02716f122dd7662d5d89f5b2245ca551e2 Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Thu, 29 Jun 2017 13:59:25 +0100
+Subject: dma-buf/sw-sync: Fix the is-signaled test to handle u32 wraparound
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 61894b02716f122dd7662d5d89f5b2245ca551e2 upstream.
+
+Use the canonical __dma_fence_is_later() to compare the fence seqno
+against the timeline seqno to check if the fence is signaled.
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Cc: Sumit Semwal <sumit.semwal@linaro.org>
+Cc: Sean Paul <seanpaul@chromium.org>
+Cc: Gustavo Padovan <gustavo@padovan.org>
+Reviewed-by: Sean Paul <seanpaul@chromium.org>
+Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
+Link: http://patchwork.freedesktop.org/patch/msgid/20170629125930.821-2-chris@chris-wilson.co.uk
+[s/dma_fence/fence/g - gregkh]
+Cc: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma-buf/sw_sync.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/dma-buf/sw_sync.c
++++ b/drivers/dma-buf/sw_sync.c
+@@ -219,7 +219,7 @@ static bool timeline_fence_signaled(stru
+ {
+ struct sync_timeline *parent = fence_parent(fence);
+
+- return (fence->seqno > parent->value) ? false : true;
++ return !__fence_is_later(fence->seqno, parent->value);
+ }
+
+ static bool timeline_fence_enable_signaling(struct fence *fence)
--- /dev/null
+From 8f66d3aa1735bc95ae58d846a157357e8d41abb8 Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Thu, 29 Jun 2017 13:59:26 +0100
+Subject: dma-buf/sw-sync: Prevent user overflow on timeline advance
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 8f66d3aa1735bc95ae58d846a157357e8d41abb8 upstream.
+
+The timeline is u32, which limits any single advance to INT_MAX so that
+we can detect all fences that need signaling.
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Cc: Sumit Semwal <sumit.semwal@linaro.org>
+Cc: Sean Paul <seanpaul@chromium.org>
+Cc: Gustavo Padovan <gustavo@padovan.org>
+Reviewed-by: Sean Paul <seanpaul@chromium.org>
+Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
+Link: http://patchwork.freedesktop.org/patch/msgid/20170629125930.821-3-chris@chris-wilson.co.uk
+[s/dma_fence/fence/g - gregkh]
+Cc: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma-buf/sw_sync.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/dma-buf/sw_sync.c
++++ b/drivers/dma-buf/sw_sync.c
+@@ -345,6 +345,11 @@ static long sw_sync_ioctl_inc(struct syn
+ if (copy_from_user(&value, (void __user *)arg, sizeof(value)))
+ return -EFAULT;
+
++ while (value > INT_MAX) {
++ sync_timeline_signal(obj, INT_MAX);
++ value -= INT_MAX;
++ }
++
+ sync_timeline_signal(obj, value);
+
+ return 0;
--- /dev/null
+From a6aa8fca4d792c72947e341d7842d2f700534335 Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Thu, 29 Jun 2017 13:59:27 +0100
+Subject: dma-buf/sw-sync: Reduce irqsave/irqrestore from known context
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit a6aa8fca4d792c72947e341d7842d2f700534335 upstream.
+
+If we know the context under which we are called, then we can use the
+simpler form of spin_lock_irq (saving the save/restore).
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Cc: Sumit Semwal <sumit.semwal@linaro.org>
+Cc: Sean Paul <seanpaul@chromium.org>
+Cc: Gustavo Padovan <gustavo@padovan.org>
+Reviewed-by: Sean Paul <seanpaul@chromium.org>
+Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
+Link: http://patchwork.freedesktop.org/patch/msgid/20170629125930.821-4-chris@chris-wilson.co.uk
+[s/dma_fence/fence/g - gregkh]
+Cc: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma-buf/sw_sync.c | 15 +++++++++------
+ drivers/dma-buf/sync_debug.c | 14 ++++++--------
+ 2 files changed, 15 insertions(+), 14 deletions(-)
+
+--- a/drivers/dma-buf/sw_sync.c
++++ b/drivers/dma-buf/sw_sync.c
+@@ -135,12 +135,11 @@ static void sync_timeline_put(struct syn
+ */
+ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc)
+ {
+- unsigned long flags;
+ struct sync_pt *pt, *next;
+
+ trace_sync_timeline(obj);
+
+- spin_lock_irqsave(&obj->child_list_lock, flags);
++ spin_lock_irq(&obj->child_list_lock);
+
+ obj->value += inc;
+
+@@ -150,7 +149,7 @@ static void sync_timeline_signal(struct
+ list_del_init(&pt->active_list);
+ }
+
+- spin_unlock_irqrestore(&obj->child_list_lock, flags);
++ spin_unlock_irq(&obj->child_list_lock);
+ }
+
+ /**
+@@ -167,7 +166,6 @@ static void sync_timeline_signal(struct
+ static struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size,
+ unsigned int value)
+ {
+- unsigned long flags;
+ struct sync_pt *pt;
+
+ if (size < sizeof(*pt))
+@@ -177,13 +175,16 @@ static struct sync_pt *sync_pt_create(st
+ if (!pt)
+ return NULL;
+
+- spin_lock_irqsave(&obj->child_list_lock, flags);
++ spin_lock_irq(&obj->child_list_lock);
++
+ sync_timeline_get(obj);
+ fence_init(&pt->base, &timeline_fence_ops, &obj->child_list_lock,
+ obj->context, 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);
++
++ spin_unlock_irq(&obj->child_list_lock);
++
+ return pt;
+ }
+
+@@ -206,9 +207,11 @@ static void timeline_fence_release(struc
+ unsigned long flags;
+
+ spin_lock_irqsave(fence->lock, flags);
++
+ list_del(&pt->child_list);
+ if (!list_empty(&pt->active_list))
+ list_del(&pt->active_list);
++
+ spin_unlock_irqrestore(fence->lock, flags);
+
+ sync_timeline_put(parent);
+--- a/drivers/dma-buf/sync_debug.c
++++ b/drivers/dma-buf/sync_debug.c
+@@ -116,17 +116,16 @@ static void sync_print_fence(struct seq_
+ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj)
+ {
+ struct list_head *pos;
+- unsigned long flags;
+
+ seq_printf(s, "%s: %d\n", obj->name, obj->value);
+
+- spin_lock_irqsave(&obj->child_list_lock, flags);
++ spin_lock_irq(&obj->child_list_lock);
+ list_for_each(pos, &obj->child_list_head) {
+ struct sync_pt *pt =
+ container_of(pos, struct sync_pt, child_list);
+ sync_print_fence(s, &pt->base, false);
+ }
+- spin_unlock_irqrestore(&obj->child_list_lock, flags);
++ spin_unlock_irq(&obj->child_list_lock);
+ }
+
+ static void sync_print_sync_file(struct seq_file *s,
+@@ -149,12 +148,11 @@ static void sync_print_sync_file(struct
+
+ 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);
++ spin_lock_irq(&sync_timeline_list_lock);
+ list_for_each(pos, &sync_timeline_list_head) {
+ struct sync_timeline *obj =
+ container_of(pos, struct sync_timeline,
+@@ -163,11 +161,11 @@ static int sync_debugfs_show(struct seq_
+ sync_print_obj(s, obj);
+ seq_puts(s, "\n");
+ }
+- spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
++ spin_unlock_irq(&sync_timeline_list_lock);
+
+ seq_puts(s, "fences:\n--------------\n");
+
+- spin_lock_irqsave(&sync_file_list_lock, flags);
++ spin_lock_irq(&sync_file_list_lock);
+ list_for_each(pos, &sync_file_list_head) {
+ struct sync_file *sync_file =
+ container_of(pos, struct sync_file, sync_file_list);
+@@ -175,7 +173,7 @@ static int sync_debugfs_show(struct seq_
+ sync_print_sync_file(s, sync_file);
+ seq_puts(s, "\n");
+ }
+- spin_unlock_irqrestore(&sync_file_list_lock, flags);
++ spin_unlock_irq(&sync_file_list_lock);
+ return 0;
+ }
+
--- /dev/null
+From 3b52ce44e720c240afc4c4b03140d7b7811b23bd Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Thu, 29 Jun 2017 13:59:28 +0100
+Subject: dma-buf/sw-sync: sync_pt is private and of fixed size
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 3b52ce44e720c240afc4c4b03140d7b7811b23bd upstream.
+
+Since sync_pt is only allocated from a single location and is no longer
+the base class for fences (that is struct dma_fence) it no longer needs
+a generic unsized allocator.
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Cc: Sumit Semwal <sumit.semwal@linaro.org>
+Cc: Sean Paul <seanpaul@chromium.org>
+Cc: Gustavo Padovan <gustavo@padovan.org>
+Reviewed-by: Sean Paul <seanpaul@chromium.org>
+Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
+Link: http://patchwork.freedesktop.org/patch/msgid/20170629125930.821-5-chris@chris-wilson.co.uk
+[s/dma_fence/fence/g - gregkh]
+Cc: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma-buf/sw_sync.c | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+--- a/drivers/dma-buf/sw_sync.c
++++ b/drivers/dma-buf/sw_sync.c
+@@ -155,7 +155,6 @@ static void sync_timeline_signal(struct
+ /**
+ * 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 sync_pt as a child of @parent. @size bytes will be
+@@ -163,15 +162,12 @@ static void sync_timeline_signal(struct
+ * the generic sync_timeline struct. Returns the sync_pt object or
+ * NULL in case of error.
+ */
+-static struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size,
+- unsigned int value)
++static struct sync_pt *sync_pt_create(struct sync_timeline *obj,
++ unsigned int value)
+ {
+ struct sync_pt *pt;
+
+- if (size < sizeof(*pt))
+- return NULL;
+-
+- pt = kzalloc(size, GFP_KERNEL);
++ pt = kzalloc(sizeof(*pt), GFP_KERNEL);
+ if (!pt)
+ return NULL;
+
+@@ -312,7 +308,7 @@ static long sw_sync_ioctl_create_fence(s
+ goto err;
+ }
+
+- pt = sync_pt_create(obj, sizeof(*pt), data.value);
++ pt = sync_pt_create(obj, data.value);
+ if (!pt) {
+ err = -ENOMEM;
+ goto err;
--- /dev/null
+From f1e8c67123cf171e2b0357e885e426328b241d7d Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Thu, 29 Jun 2017 22:12:53 +0100
+Subject: dma-buf/sw-sync: Use an rbtree to sort fences in the timeline
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit f1e8c67123cf171e2b0357e885e426328b241d7d upstream.
+
+Reduce the list iteration when incrementing the timeline by storing the
+fences in increasing order.
+
+v2: Prevent spinlock recursion on free during create
+v3: Fixup rebase conflict inside comments that escaped the compiler.
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Cc: Sumit Semwal <sumit.semwal@linaro.org>
+Cc: Sean Paul <seanpaul@chromium.org>
+Cc: Gustavo Padovan <gustavo@padovan.org>
+Reviewed-by: Sean Paul <seanpaul@chromium.org>
+Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
+Link: http://patchwork.freedesktop.org/patch/msgid/20170629211253.22766-1-chris@chris-wilson.co.uk
+[s/dma_fence/fence/g - gregkh]
+Cc: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma-buf/sw_sync.c | 49 +++++++++++++++++++++++++++++++++++++------
+ drivers/dma-buf/sync_debug.h | 5 ++++
+ 2 files changed, 48 insertions(+), 6 deletions(-)
+
+--- a/drivers/dma-buf/sw_sync.c
++++ b/drivers/dma-buf/sw_sync.c
+@@ -96,6 +96,7 @@ struct sync_timeline *sync_timeline_crea
+ obj->context = fence_context_alloc(1);
+ strlcpy(obj->name, name, sizeof(obj->name));
+
++ obj->pt_tree = RB_ROOT;
+ INIT_LIST_HEAD(&obj->pt_list);
+ spin_lock_init(&obj->lock);
+
+@@ -142,9 +143,13 @@ static void sync_timeline_signal(struct
+
+ obj->value += inc;
+
+- list_for_each_entry_safe(pt, next, &obj->pt_list, link)
+- if (fence_is_signaled_locked(&pt->base))
+- list_del_init(&pt->link);
++ list_for_each_entry_safe(pt, next, &obj->pt_list, link) {
++ if (!fence_is_signaled_locked(&pt->base))
++ break;
++
++ list_del_init(&pt->link);
++ rb_erase(&pt->node, &obj->pt_tree);
++ }
+
+ spin_unlock_irq(&obj->lock);
+ }
+@@ -174,8 +179,38 @@ static struct sync_pt *sync_pt_create(st
+ INIT_LIST_HEAD(&pt->link);
+
+ spin_lock_irq(&obj->lock);
+- if (!fence_is_signaled_locked(&pt->base))
+- list_add_tail(&pt->link, &obj->pt_list);
++ if (!fence_is_signaled_locked(&pt->base)) {
++ struct rb_node **p = &obj->pt_tree.rb_node;
++ struct rb_node *parent = NULL;
++
++ while (*p) {
++ struct sync_pt *other;
++ int cmp;
++
++ parent = *p;
++ other = rb_entry(parent, typeof(*pt), node);
++ cmp = value - other->base.seqno;
++ if (cmp > 0) {
++ p = &parent->rb_right;
++ } else if (cmp < 0) {
++ p = &parent->rb_left;
++ } else {
++ if (fence_get_rcu(&other->base)) {
++ fence_put(&pt->base);
++ pt = other;
++ goto unlock;
++ }
++ p = &parent->rb_left;
++ }
++ }
++ rb_link_node(&pt->node, parent, p);
++ rb_insert_color(&pt->node, &obj->pt_tree);
++
++ parent = rb_next(&pt->node);
++ list_add_tail(&pt->link,
++ parent ? &rb_entry(parent, typeof(*pt), node)->link : &obj->pt_list);
++ }
++unlock:
+ spin_unlock_irq(&obj->lock);
+
+ return pt;
+@@ -202,8 +237,10 @@ static void timeline_fence_release(struc
+ unsigned long flags;
+
+ spin_lock_irqsave(fence->lock, flags);
+- if (!list_empty(&pt->link))
++ if (!list_empty(&pt->link)) {
+ list_del(&pt->link);
++ rb_erase(&pt->node, &parent->pt_tree);
++ }
+ spin_unlock_irqrestore(fence->lock, flags);
+ }
+
+--- a/drivers/dma-buf/sync_debug.h
++++ b/drivers/dma-buf/sync_debug.h
+@@ -14,6 +14,7 @@
+ #define _LINUX_SYNC_H
+
+ #include <linux/list.h>
++#include <linux/rbtree.h>
+ #include <linux/spinlock.h>
+ #include <linux/fence.h>
+
+@@ -25,6 +26,7 @@
+ * @kref: reference count on fence.
+ * @name: name of the sync_timeline. Useful for debugging
+ * @lock: lock protecting @pt_list and @value
++ * @pt_tree: rbtree of active (unsignaled/errored) sync_pts
+ * @pt_list: list of active (unsignaled/errored) sync_pts
+ * @sync_timeline_list: membership in global sync_timeline_list
+ */
+@@ -36,6 +38,7 @@ struct sync_timeline {
+ u64 context;
+ int value;
+
++ struct rb_root pt_tree;
+ struct list_head pt_list;
+ spinlock_t lock;
+
+@@ -51,10 +54,12 @@ static inline struct sync_timeline *fenc
+ * struct sync_pt - sync_pt object
+ * @base: base fence object
+ * @link: link on the sync timeline's list
++ * @node: node in the sync timeline's tree
+ */
+ struct sync_pt {
+ struct fence base;
+ struct list_head link;
++ struct rb_node node;
+ };
+
+ #ifdef CONFIG_SW_SYNC
--- /dev/null
+From 3792b7c1a70815fe4e954221c096f9278638fd21 Mon Sep 17 00:00:00 2001
+From: Gustavo Padovan <gustavo.padovan@collabora.com>
+Date: Sat, 29 Jul 2017 12:22:16 -0300
+Subject: dma-buf/sw_sync: clean up list before signaling the fence
+
+From: Gustavo Padovan <gustavo.padovan@collabora.com>
+
+commit 3792b7c1a70815fe4e954221c096f9278638fd21 upstream.
+
+If userspace already dropped its own reference by closing the sw_sync
+fence fd we might end up in a deadlock where
+dma_fence_is_signaled_locked() will trigger the release of the fence and
+thus try to hold the lock to remove the fence from the list.
+
+dma_fence_is_signaled_locked() tries to release/free the fence and hold
+the lock in the process.
+
+We fix that by changing the order operation and clean up the list and
+rb-tree first.
+
+v2: Drop fence get/put dance and manipulate the list first (Chris Wilson)
+
+Cc: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
+Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
+Link: https://patchwork.freedesktop.org/patch/msgid/20170729152217.8362-2-gustavo@padovan.org
+[s/dma_fence/fence/g - gregkh]
+Cc: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma-buf/sw_sync.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/drivers/dma-buf/sw_sync.c
++++ b/drivers/dma-buf/sw_sync.c
+@@ -213,11 +213,21 @@ static void sync_timeline_signal(struct
+ obj->value += inc;
+
+ list_for_each_entry_safe(pt, next, &obj->pt_list, link) {
+- if (!fence_is_signaled_locked(&pt->base))
++ if (!timeline_fence_signaled(&pt->base))
+ break;
+
+ list_del_init(&pt->link);
+ rb_erase(&pt->node, &obj->pt_tree);
++
++ /*
++ * A signal callback may release the last reference to this
++ * fence, causing it to be freed. That operation has to be
++ * last to avoid a use after free inside this loop, and must
++ * be after we remove the fence from the timeline in order to
++ * prevent deadlocking on timeline->lock inside
++ * timeline_fence_release().
++ */
++ fence_signal_locked(&pt->base);
+ }
+
+ spin_unlock_irq(&obj->lock);
--- /dev/null
+From ea4d5a270b57fa8d4871f372ca9b97b7697fdfda Mon Sep 17 00:00:00 2001
+From: Dominik Behr <dbehr@chromium.org>
+Date: Thu, 7 Sep 2017 16:02:46 -0300
+Subject: dma-buf/sw_sync: force signal all unsignaled fences on dying timeline
+
+From: Dominik Behr <dbehr@chromium.org>
+
+commit ea4d5a270b57fa8d4871f372ca9b97b7697fdfda upstream.
+
+To avoid hanging userspace components that might have been waiting on the
+active fences of the destroyed timeline we need to signal with error all
+remaining fences on such timeline.
+
+This restore the default behaviour of the Android sw_sync framework, which
+Android still relies on. It was broken on the dma fence conversion a few
+years ago and never fixed.
+
+v2: Do not bother with cleanup do the list (Chris Wilson)
+
+Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Dominik Behr <dbehr@chromium.org>
+Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20170907190246.16425-2-gustavo@padovan.org
+[s/dma_fence/fence/g - gregkh]
+Cc: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma-buf/sw_sync.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/drivers/dma-buf/sw_sync.c
++++ b/drivers/dma-buf/sw_sync.c
+@@ -321,8 +321,16 @@ static int sw_sync_debugfs_open(struct i
+ static int sw_sync_debugfs_release(struct inode *inode, struct file *file)
+ {
+ struct sync_timeline *obj = file->private_data;
++ struct sync_pt *pt, *next;
+
+- smp_wmb();
++ spin_lock_irq(&obj->lock);
++
++ list_for_each_entry_safe(pt, next, &obj->pt_list, link) {
++ fence_set_error(&pt->base, -ENOENT);
++ fence_signal_locked(&pt->base);
++ }
++
++ spin_unlock_irq(&obj->lock);
+
+ sync_timeline_put(obj);
+ return 0;
--- /dev/null
+From 150b6a9d7d6fffb95c0a5349960a10569e8218b5 Mon Sep 17 00:00:00 2001
+From: Gustavo Padovan <gustavo.padovan@collabora.com>
+Date: Sat, 29 Jul 2017 12:22:15 -0300
+Subject: dma-buf/sw_sync: move timeline_fence_ops around
+
+From: Gustavo Padovan <gustavo.padovan@collabora.com>
+
+commit 150b6a9d7d6fffb95c0a5349960a10569e8218b5 upstream.
+
+We are going to use timeline_fence_signaled() in a internal function in
+the next commit.
+
+Cc: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
+Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
+Link: https://patchwork.freedesktop.org/patch/msgid/20170729152217.8362-1-gustavo@padovan.org
+[s/dma_fence/fence/g - gregkh]
+Cc: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma-buf/sw_sync.c | 138 +++++++++++++++++++++++-----------------------
+ 1 file changed, 69 insertions(+), 69 deletions(-)
+
+--- a/drivers/dma-buf/sw_sync.c
++++ b/drivers/dma-buf/sw_sync.c
+@@ -125,6 +125,75 @@ static void sync_timeline_put(struct syn
+ kref_put(&obj->kref, sync_timeline_free);
+ }
+
++static const char *timeline_fence_get_driver_name(struct fence *fence)
++{
++ return "sw_sync";
++}
++
++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_pt *pt = fence_to_sync_pt(fence);
++ struct sync_timeline *parent = fence_parent(fence);
++
++ if (!list_empty(&pt->link)) {
++ unsigned long flags;
++
++ spin_lock_irqsave(fence->lock, flags);
++ if (!list_empty(&pt->link)) {
++ list_del(&pt->link);
++ rb_erase(&pt->node, &parent->pt_tree);
++ }
++ 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_is_later(fence->seqno, parent->value);
++}
++
++static bool timeline_fence_enable_signaling(struct fence *fence)
++{
++ return true;
++}
++
++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,
++ .fence_value_str = timeline_fence_value_str,
++ .timeline_value_str = timeline_fence_timeline_value_str,
++};
++
+ /**
+ * sync_timeline_signal() - signal a status change on a sync_timeline
+ * @obj: sync_timeline to signal
+@@ -216,75 +285,6 @@ unlock:
+ return pt;
+ }
+
+-static const char *timeline_fence_get_driver_name(struct fence *fence)
+-{
+- return "sw_sync";
+-}
+-
+-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_pt *pt = fence_to_sync_pt(fence);
+- struct sync_timeline *parent = fence_parent(fence);
+-
+- if (!list_empty(&pt->link)) {
+- unsigned long flags;
+-
+- spin_lock_irqsave(fence->lock, flags);
+- if (!list_empty(&pt->link)) {
+- list_del(&pt->link);
+- rb_erase(&pt->node, &parent->pt_tree);
+- }
+- 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_is_later(fence->seqno, parent->value);
+-}
+-
+-static bool timeline_fence_enable_signaling(struct fence *fence)
+-{
+- return true;
+-}
+-
+-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,
+- .fence_value_str = timeline_fence_value_str,
+- .timeline_value_str = timeline_fence_timeline_value_str,
+-};
+-
+ /*
+ * *WARNING*
+ *
--- /dev/null
+From 83dd1376fd92f33bdeca9e83d479534a4e7f870b Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Wed, 4 Jan 2017 14:12:20 +0000
+Subject: dma-fence: Clear fence->status during dma_fence_init()
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 83dd1376fd92f33bdeca9e83d479534a4e7f870b upstream.
+
+As the fence->status is an optional field that may be set before
+dma_fence_signal() is called to convey that the fence completed with an
+error, we have to ensure that it is always set to zero on initialisation
+so that the typical use (i.e. unset) always flags a successful completion.
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Reviewed-by: Sumit Semwal <sumit.semwal@linaro.org>
+Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
+Link: http://patchwork.freedesktop.org/patch/msgid/20170104141222.6992-1-chris@chris-wilson.co.uk
+[s/dma_fence/fence/g - gregkh]
+Cc: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma-buf/fence.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/dma-buf/fence.c
++++ b/drivers/dma-buf/fence.c
+@@ -526,6 +526,7 @@ fence_init(struct fence *fence, const st
+ fence->context = context;
+ fence->seqno = seqno;
+ fence->flags = 0UL;
++ fence->status = 0;
+
+ trace_fence_init(fence);
+ }
--- /dev/null
+From a009e975da5c7d42a7f5eaadc54946eb5f76c9af Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Wed, 4 Jan 2017 14:12:22 +0000
+Subject: dma-fence: Introduce drm_fence_set_error() helper
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit a009e975da5c7d42a7f5eaadc54946eb5f76c9af upstream.
+
+The dma_fence.error field (formerly known as dma_fence.status) is an
+optional field that may be set by drivers before calling
+dma_fence_signal(). The field can be used to indicate that the fence was
+completed in err rather than with success, and is visible to other
+consumers of the fence and to userspace via sync_file.
+
+This patch renames the field from status to error so that its meaning is
+hopefully more clear (and distinct from dma_fence_get_status() which is
+a composite between the error state and signal state) and adds a helper
+that validates the preconditions of when it is suitable to adjust the
+error field.
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Reviewed-by: Sumit Semwal <sumit.semwal@linaro.org>
+Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
+Link: http://patchwork.freedesktop.org/patch/msgid/20170104141222.6992-3-chris@chris-wilson.co.uk
+[s/dma_fence/fence/g - gregkh]
+Cc: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma-buf/fence.c | 2 +-
+ include/linux/fence.h | 30 +++++++++++++++++++++++++-----
+ 2 files changed, 26 insertions(+), 6 deletions(-)
+
+--- a/drivers/dma-buf/fence.c
++++ b/drivers/dma-buf/fence.c
+@@ -551,7 +551,7 @@ fence_init(struct fence *fence, const st
+ fence->context = context;
+ fence->seqno = seqno;
+ fence->flags = 0UL;
+- fence->status = 0;
++ fence->error = 0;
+
+ trace_fence_init(fence);
+ }
+--- a/include/linux/fence.h
++++ b/include/linux/fence.h
+@@ -47,7 +47,7 @@ struct fence_cb;
+ * can be compared to decide which fence would be signaled later.
+ * @flags: A mask of FENCE_FLAG_* defined below
+ * @timestamp: Timestamp when the fence was signaled.
+- * @status: Optional, only valid if < 0, must be set before calling
++ * @error: Optional, only valid if < 0, must be set before calling
+ * fence_signal, indicates that the fence has completed with an error.
+ *
+ * the flags member must be manipulated and read using the appropriate
+@@ -79,7 +79,7 @@ struct fence {
+ unsigned seqno;
+ unsigned long flags;
+ ktime_t timestamp;
+- int status;
++ int error;
+ };
+
+ enum fence_flag_bits {
+@@ -132,7 +132,7 @@ struct fence_cb {
+ * or some failure occurred that made it impossible to enable
+ * signaling. True indicates successful enabling.
+ *
+- * fence->status may be set in enable_signaling, but only when false is
++ * fence->error may be set in enable_signaling, but only when false is
+ * returned.
+ *
+ * Calling fence_signal before enable_signaling is called allows
+@@ -144,7 +144,7 @@ struct fence_cb {
+ * the second time will be a noop since it was already signaled.
+ *
+ * Notes on signaled:
+- * May set fence->status if returning true.
++ * May set fence->error if returning true.
+ *
+ * Notes on wait:
+ * Must not be NULL, set to fence_default_wait for default implementation.
+@@ -351,13 +351,33 @@ static inline struct fence *fence_later(
+ static inline int fence_get_status_locked(struct fence *fence)
+ {
+ if (fence_is_signaled_locked(fence))
+- return fence->status < 0 ? fence->status : 1;
++ return fence->error ?: 1;
+ else
+ return 0;
+ }
+
+ int fence_get_status(struct fence *fence);
+
++/**
++ * fence_set_error - flag an error condition on the fence
++ * @fence: [in] the fence
++ * @error: [in] the error to store
++ *
++ * Drivers can supply an optional error status condition before they signal
++ * the fence, to indicate that the fence was completed due to an error
++ * rather than success. This must be set before signaling (so that the value
++ * is visible before any waiters on the signal callback are woken). This
++ * helper exists to help catching erroneous setting of #fence.error.
++ */
++static inline void fence_set_error(struct fence *fence,
++ int error)
++{
++ BUG_ON(test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags));
++ BUG_ON(error >= 0 || error < -MAX_ERRNO);
++
++ fence->error = error;
++}
++
+ signed long fence_wait_timeout(struct fence *, bool intr, signed long timeout);
+ signed long fence_wait_any_timeout(struct fence **fences, uint32_t count,
+ bool intr, signed long timeout);
--- /dev/null
+From d6c99f4bf093a58d3ab47caaec74b81f18bc4e3f Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Wed, 4 Jan 2017 14:12:21 +0000
+Subject: dma-fence: Wrap querying the fence->status
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit d6c99f4bf093a58d3ab47caaec74b81f18bc4e3f upstream.
+
+The fence->status is an optional field that is only valid once the fence
+has been signaled. (Driver may fill the fence->status with an error code
+prior to calling dma_fence_signal().) Given the restriction upon its
+validity, wrap querying of the fence->status into a helper
+dma_fence_get_status().
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Reviewed-by: Sumit Semwal <sumit.semwal@linaro.org>
+Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
+Link: http://patchwork.freedesktop.org/patch/msgid/20170104141222.6992-2-chris@chris-wilson.co.uk
+[s/dma_fence/fence/g - gregkh]
+Cc: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma-buf/fence.c | 25 +++++++++++++++++++++++++
+ drivers/dma-buf/sync_debug.c | 20 ++++++++++----------
+ drivers/dma-buf/sync_file.c | 6 ++----
+ include/linux/fence.h | 24 ++++++++++++++++++++++++
+ 4 files changed, 61 insertions(+), 14 deletions(-)
+
+--- a/drivers/dma-buf/fence.c
++++ b/drivers/dma-buf/fence.c
+@@ -281,6 +281,31 @@ int fence_add_callback(struct fence *fen
+ EXPORT_SYMBOL(fence_add_callback);
+
+ /**
++ * fence_get_status - returns the status upon completion
++ * @fence: [in] the fence to query
++ *
++ * This wraps fence_get_status_locked() to return the error status
++ * condition on a signaled fence. See fence_get_status_locked() for more
++ * details.
++ *
++ * Returns 0 if the fence has not yet been signaled, 1 if the fence has
++ * been signaled without an error condition, or a negative error code
++ * if the fence has been completed in err.
++ */
++int fence_get_status(struct fence *fence)
++{
++ unsigned long flags;
++ int status;
++
++ spin_lock_irqsave(fence->lock, flags);
++ status = fence_get_status_locked(fence);
++ spin_unlock_irqrestore(fence->lock, flags);
++
++ return status;
++}
++EXPORT_SYMBOL(fence_get_status);
++
++/**
+ * fence_remove_callback - remove a callback from the signaling list
+ * @fence: [in] the fence to wait on
+ * @cb: [in] the callback to remove
+--- a/drivers/dma-buf/sync_debug.c
++++ b/drivers/dma-buf/sync_debug.c
+@@ -62,29 +62,29 @@ void sync_file_debug_remove(struct sync_
+
+ static const char *sync_status_str(int status)
+ {
+- if (status == 0)
+- return "signaled";
++ if (status < 0)
++ return "error";
+
+ if (status > 0)
+- return "active";
++ return "signaled";
+
+- return "error";
++ return "active";
+ }
+
+-static void sync_print_fence(struct seq_file *s, struct fence *fence, bool show)
++static void sync_print_fence(struct seq_file *s,
++ struct fence *fence, bool show)
+ {
+- int status = 1;
+ struct sync_timeline *parent = fence_parent(fence);
++ int status;
+
+- if (fence_is_signaled_locked(fence))
+- status = fence->status;
++ status = fence_get_status_locked(fence);
+
+ seq_printf(s, " %s%sfence %s",
+ show ? parent->name : "",
+ show ? "_" : "",
+ sync_status_str(status));
+
+- if (status <= 0) {
++ if (status) {
+ struct timespec64 ts64 =
+ ktime_to_timespec64(fence->timestamp);
+
+@@ -133,7 +133,7 @@ static void sync_print_sync_file(struct
+ int i;
+
+ seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name,
+- sync_status_str(!fence_is_signaled(sync_file->fence)));
++ sync_status_str(fence_get_status(sync_file->fence)));
+
+ if (fence_is_array(sync_file->fence)) {
+ struct fence_array *array = to_fence_array(sync_file->fence);
+--- a/drivers/dma-buf/sync_file.c
++++ b/drivers/dma-buf/sync_file.c
+@@ -377,10 +377,8 @@ static void sync_fill_fence_info(struct
+ sizeof(info->obj_name));
+ strlcpy(info->driver_name, fence->ops->get_driver_name(fence),
+ sizeof(info->driver_name));
+- if (fence_is_signaled(fence))
+- info->status = fence->status >= 0 ? 1 : fence->status;
+- else
+- info->status = 0;
++
++ info->status = fence_get_status(fence);
+ info->timestamp_ns = ktime_to_ns(fence->timestamp);
+ }
+
+--- a/include/linux/fence.h
++++ b/include/linux/fence.h
+@@ -334,6 +334,30 @@ static inline struct fence *fence_later(
+ return fence_is_signaled(f2) ? NULL : f2;
+ }
+
++/**
++ * fence_get_status_locked - returns the status upon completion
++ * @fence: [in] the fence to query
++ *
++ * Drivers can supply an optional error status condition before they signal
++ * the fence (to indicate whether the fence was completed due to an error
++ * rather than success). The value of the status condition is only valid
++ * if the fence has been signaled, fence_get_status_locked() first checks
++ * the signal state before reporting the error status.
++ *
++ * Returns 0 if the fence has not yet been signaled, 1 if the fence has
++ * been signaled without an error condition, or a negative error code
++ * if the fence has been completed in err.
++ */
++static inline int fence_get_status_locked(struct fence *fence)
++{
++ if (fence_is_signaled_locked(fence))
++ return fence->status < 0 ? fence->status : 1;
++ else
++ return 0;
++}
++
++int fence_get_status(struct fence *fence);
++
+ signed long fence_wait_timeout(struct fence *, bool intr, signed long timeout);
+ signed long fence_wait_any_timeout(struct fence **fences, uint32_t count,
+ bool intr, signed long timeout);
cec-initiator-should-be-the-same-as-the-destination-for-poll.patch
xen-netback-vif-counters-from-int-long-to-u64.patch
net-fec-fix-multicast-filtering-hardware-setup.patch
+dma-buf-dma-fence-extract-__dma_fence_is_later.patch
+dma-buf-sw-sync-fix-the-is-signaled-test-to-handle-u32-wraparound.patch
+dma-buf-sw-sync-prevent-user-overflow-on-timeline-advance.patch
+dma-buf-sw-sync-reduce-irqsave-irqrestore-from-known-context.patch
+dma-buf-sw-sync-sync_pt-is-private-and-of-fixed-size.patch
+dma-buf-sw-sync-fix-locking-around-sync_timeline-lists.patch
+dma-buf-sw-sync-use-an-rbtree-to-sort-fences-in-the-timeline.patch
+dma-buf-sw_sync-move-timeline_fence_ops-around.patch
+dma-buf-sw_sync-clean-up-list-before-signaling-the-fence.patch
+dma-fence-clear-fence-status-during-dma_fence_init.patch
+dma-fence-wrap-querying-the-fence-status.patch
+dma-fence-introduce-drm_fence_set_error-helper.patch
+dma-buf-sw_sync-force-signal-all-unsignaled-fences-on-dying-timeline.patch