aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma-buf/sw_sync.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2017-06-29 22:05:32 +0100
committerGustavo Padovan <gustavo.padovan@collabora.com>2017-06-29 18:53:47 -0300
commitd3862e44daa7a0c94d2f6193502a8c49379acfce (patch)
tree6716a8b2f9830b5b052837f2eddd40c10e64b124 /drivers/dma-buf/sw_sync.c
parentdma-buf/sw-sync: sync_pt is private and of fixed size (diff)
downloadlinux-dev-d3862e44daa7a0c94d2f6193502a8c49379acfce.tar.xz
linux-dev-d3862e44daa7a0c94d2f6193502a8c49379acfce.zip
dma-buf/sw-sync: Fix locking around sync_timeline lists
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
Diffstat (limited to 'drivers/dma-buf/sw_sync.c')
-rw-r--r--drivers/dma-buf/sw_sync.c48
1 files changed, 19 insertions, 29 deletions
diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
index 6effa1ce010e..f20d18c421a3 100644
--- a/drivers/dma-buf/sw_sync.c
+++ b/drivers/dma-buf/sw_sync.c
@@ -96,9 +96,8 @@ static struct sync_timeline *sync_timeline_create(const char *name)
obj->context = dma_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 sync_timeline *obj, unsigned int inc)
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 (dma_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(struct sync_timeline *obj,
if (!pt)
return NULL;
- spin_lock_irq(&obj->child_list_lock);
-
sync_timeline_get(obj);
- dma_fence_init(&pt->base, &timeline_fence_ops, &obj->child_list_lock,
+ dma_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 (!dma_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(struct dma_fence *fence)
{
struct sync_pt *pt = dma_fence_to_sync_pt(fence);
struct sync_timeline *parent = dma_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);
dma_fence_free(fence);
@@ -223,13 +220,6 @@ static bool timeline_fence_signaled(struct dma_fence *fence)
static bool timeline_fence_enable_signaling(struct dma_fence *fence)
{
- struct sync_pt *pt = dma_fence_to_sync_pt(fence);
- struct sync_timeline *parent = dma_fence_parent(fence);
-
- if (timeline_fence_signaled(fence))
- return false;
-
- list_add_tail(&pt->active_list, &parent->active_list_head);
return true;
}