Loading drivers/gpu/msm/kgsl_timeline.c +19 −40 Original line number Diff line number Diff line Loading @@ -14,8 +14,6 @@ #include "kgsl_timeline.h" #include "kgsl_trace.h" static DEFINE_SPINLOCK(fence_lock); struct kgsl_timeline_fence { struct dma_fence base; struct kgsl_timeline *timeline; Loading Loading @@ -152,6 +150,7 @@ static struct kgsl_timeline *kgsl_timeline_alloc(struct kgsl_device_private *dev trace_kgsl_timeline_alloc(id, initial); spin_lock_init(&timeline->lock); spin_lock_init(&timeline->fence_lock); kref_init(&timeline->ref); Loading @@ -170,8 +169,7 @@ static void timeline_fence_release(struct dma_fence *fence) struct kgsl_timeline_fence *cur, *temp; unsigned long flags; spin_lock_irqsave(&timeline->lock, flags); spin_lock(&fence_lock); spin_lock_irqsave(&timeline->fence_lock, flags); /* If the fence is still on the active list, remove it */ list_for_each_entry_safe(cur, temp, &timeline->fences, node) { Loading @@ -181,8 +179,7 @@ static void timeline_fence_release(struct dma_fence *fence) list_del_init(&f->node); break; } spin_unlock(&fence_lock); spin_unlock_irqrestore(&timeline->lock, flags); spin_unlock_irqrestore(&timeline->fence_lock, flags); trace_kgsl_timeline_fence_release(f->timeline->id, fence->seqno); kgsl_timeline_put(f->timeline); Loading Loading @@ -243,17 +240,17 @@ static void kgsl_timeline_add_fence(struct kgsl_timeline *timeline, struct kgsl_timeline_fence *entry; unsigned long flags; spin_lock_irqsave(&fence_lock, flags); spin_lock_irqsave(&timeline->fence_lock, flags); list_for_each_entry(entry, &timeline->fences, node) { if (fence->base.seqno < entry->base.seqno) { list_add_tail(&fence->node, &entry->node); spin_unlock_irqrestore(&fence_lock, flags); spin_unlock_irqrestore(&timeline->fence_lock, flags); return; } } list_add_tail(&fence->node, &timeline->fences); spin_unlock_irqrestore(&fence_lock, flags); spin_unlock_irqrestore(&timeline->fence_lock, flags); } void kgsl_timeline_signal(struct kgsl_timeline *timeline, u64 seqno) Loading @@ -272,22 +269,18 @@ void kgsl_timeline_signal(struct kgsl_timeline *timeline, u64 seqno) timeline->value = seqno; /* Copy the list out so we can walk it without holding the lock */ spin_lock(&fence_lock); list_replace_init(&timeline->fences, &temp); spin_unlock(&fence_lock); list_for_each_entry_safe(fence, tmp, &temp, node) { spin_lock(&timeline->fence_lock); list_for_each_entry_safe(fence, tmp, &timeline->fences, node) { if (timeline_fence_signaled(&fence->base)) { list_del_init(&fence->node); dma_fence_signal_locked(&fence->base); dma_fence_get(&fence->base); list_move(&fence->node, &temp); } } spin_unlock(&timeline->fence_lock); /* Put the active fences back in the timeline list */ list_for_each_entry_safe(fence, tmp, &temp, node) { list_del_init(&fence->node); kgsl_timeline_add_fence(timeline, fence); dma_fence_signal_locked(&fence->base); dma_fence_put(&fence->base); } unlock: Loading Loading @@ -553,33 +546,19 @@ long kgsl_ioctl_timeline_destroy(struct kgsl_device_private *dev_priv, INIT_LIST_HEAD(&temp); spin_lock_irq(&timeline->lock); /* Copy any still pending fences to a temporary list */ spin_lock(&fence_lock); spin_lock(&timeline->fence_lock); list_for_each_entry_safe(fence, tmp, &timeline->fences, node) dma_fence_get(&fence->base); list_replace_init(&timeline->fences, &temp); spin_unlock(&fence_lock); spin_unlock(&timeline->fence_lock); /* * Set an error on each still pending fence and signal * them to release any callbacks. Hold the refcount * to avoid fence getting destroyed during signaling. */ spin_lock_irq(&timeline->lock); list_for_each_entry_safe(fence, tmp, &temp, node) { dma_fence_get(&fence->base); dma_fence_set_error(&fence->base, -ENOENT); dma_fence_signal_locked(&fence->base); } spin_unlock_irq(&timeline->lock); /* * Put the fence refcount taken above outside lock * to avoid spinlock recursion during fence release. */ list_for_each_entry_safe(fence, tmp, &temp, node) { list_del_init(&fence->node); dma_fence_put(&fence->base); } spin_unlock_irq(&timeline->lock); kgsl_timeline_put(timeline); Loading drivers/gpu/msm/kgsl_timeline.h +3 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,9 @@ struct kgsl_timeline { int id; /** @value: Current value of the timeline */ u64 value; /** @lock: Lock to protect @fences */ /** @fence_lock: Lock to protect @fences */ spinlock_t fence_lock; /** @lock: Lock to use for locking each fence in @fences */ spinlock_t lock; /** @ref: Reference count for the struct */ struct kref ref; Loading Loading
drivers/gpu/msm/kgsl_timeline.c +19 −40 Original line number Diff line number Diff line Loading @@ -14,8 +14,6 @@ #include "kgsl_timeline.h" #include "kgsl_trace.h" static DEFINE_SPINLOCK(fence_lock); struct kgsl_timeline_fence { struct dma_fence base; struct kgsl_timeline *timeline; Loading Loading @@ -152,6 +150,7 @@ static struct kgsl_timeline *kgsl_timeline_alloc(struct kgsl_device_private *dev trace_kgsl_timeline_alloc(id, initial); spin_lock_init(&timeline->lock); spin_lock_init(&timeline->fence_lock); kref_init(&timeline->ref); Loading @@ -170,8 +169,7 @@ static void timeline_fence_release(struct dma_fence *fence) struct kgsl_timeline_fence *cur, *temp; unsigned long flags; spin_lock_irqsave(&timeline->lock, flags); spin_lock(&fence_lock); spin_lock_irqsave(&timeline->fence_lock, flags); /* If the fence is still on the active list, remove it */ list_for_each_entry_safe(cur, temp, &timeline->fences, node) { Loading @@ -181,8 +179,7 @@ static void timeline_fence_release(struct dma_fence *fence) list_del_init(&f->node); break; } spin_unlock(&fence_lock); spin_unlock_irqrestore(&timeline->lock, flags); spin_unlock_irqrestore(&timeline->fence_lock, flags); trace_kgsl_timeline_fence_release(f->timeline->id, fence->seqno); kgsl_timeline_put(f->timeline); Loading Loading @@ -243,17 +240,17 @@ static void kgsl_timeline_add_fence(struct kgsl_timeline *timeline, struct kgsl_timeline_fence *entry; unsigned long flags; spin_lock_irqsave(&fence_lock, flags); spin_lock_irqsave(&timeline->fence_lock, flags); list_for_each_entry(entry, &timeline->fences, node) { if (fence->base.seqno < entry->base.seqno) { list_add_tail(&fence->node, &entry->node); spin_unlock_irqrestore(&fence_lock, flags); spin_unlock_irqrestore(&timeline->fence_lock, flags); return; } } list_add_tail(&fence->node, &timeline->fences); spin_unlock_irqrestore(&fence_lock, flags); spin_unlock_irqrestore(&timeline->fence_lock, flags); } void kgsl_timeline_signal(struct kgsl_timeline *timeline, u64 seqno) Loading @@ -272,22 +269,18 @@ void kgsl_timeline_signal(struct kgsl_timeline *timeline, u64 seqno) timeline->value = seqno; /* Copy the list out so we can walk it without holding the lock */ spin_lock(&fence_lock); list_replace_init(&timeline->fences, &temp); spin_unlock(&fence_lock); list_for_each_entry_safe(fence, tmp, &temp, node) { spin_lock(&timeline->fence_lock); list_for_each_entry_safe(fence, tmp, &timeline->fences, node) { if (timeline_fence_signaled(&fence->base)) { list_del_init(&fence->node); dma_fence_signal_locked(&fence->base); dma_fence_get(&fence->base); list_move(&fence->node, &temp); } } spin_unlock(&timeline->fence_lock); /* Put the active fences back in the timeline list */ list_for_each_entry_safe(fence, tmp, &temp, node) { list_del_init(&fence->node); kgsl_timeline_add_fence(timeline, fence); dma_fence_signal_locked(&fence->base); dma_fence_put(&fence->base); } unlock: Loading Loading @@ -553,33 +546,19 @@ long kgsl_ioctl_timeline_destroy(struct kgsl_device_private *dev_priv, INIT_LIST_HEAD(&temp); spin_lock_irq(&timeline->lock); /* Copy any still pending fences to a temporary list */ spin_lock(&fence_lock); spin_lock(&timeline->fence_lock); list_for_each_entry_safe(fence, tmp, &timeline->fences, node) dma_fence_get(&fence->base); list_replace_init(&timeline->fences, &temp); spin_unlock(&fence_lock); spin_unlock(&timeline->fence_lock); /* * Set an error on each still pending fence and signal * them to release any callbacks. Hold the refcount * to avoid fence getting destroyed during signaling. */ spin_lock_irq(&timeline->lock); list_for_each_entry_safe(fence, tmp, &temp, node) { dma_fence_get(&fence->base); dma_fence_set_error(&fence->base, -ENOENT); dma_fence_signal_locked(&fence->base); } spin_unlock_irq(&timeline->lock); /* * Put the fence refcount taken above outside lock * to avoid spinlock recursion during fence release. */ list_for_each_entry_safe(fence, tmp, &temp, node) { list_del_init(&fence->node); dma_fence_put(&fence->base); } spin_unlock_irq(&timeline->lock); kgsl_timeline_put(timeline); Loading
drivers/gpu/msm/kgsl_timeline.h +3 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,9 @@ struct kgsl_timeline { int id; /** @value: Current value of the timeline */ u64 value; /** @lock: Lock to protect @fences */ /** @fence_lock: Lock to protect @fences */ spinlock_t fence_lock; /** @lock: Lock to use for locking each fence in @fences */ spinlock_t lock; /** @ref: Reference count for the struct */ struct kref ref; Loading