From: Christian König <ckoe...@able.fritz.box> Offload signaling fence in the sw_sync component into a work item to improve testing the real world signaling conditions.
Needs more testing before pushing it upstream! Signed-off-by: Christian König <ckoe...@able.fritz.box> --- drivers/dma-buf/sw_sync.c | 25 ++++++++++++++----------- drivers/dma-buf/sync_debug.h | 2 ++ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index 3c20f1d31cf5..43b8ac32482d 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -80,6 +80,7 @@ struct sw_sync_get_deadline { #define SW_SYNC_HAS_DEADLINE_BIT DMA_FENCE_FLAG_USER_BITS +static void sync_timeline_signal(struct work_struct *work); static const struct dma_fence_ops timeline_fence_ops; static inline struct sync_pt *dma_fence_to_sync_pt(struct dma_fence *fence) @@ -110,6 +111,7 @@ static struct sync_timeline *sync_timeline_create(const char *name) obj->pt_tree = RB_ROOT; INIT_LIST_HEAD(&obj->pt_list); + INIT_WORK(&obj->signal_work, sync_timeline_signal); spin_lock_init(&obj->lock); sync_timeline_debug_add(obj); @@ -123,6 +125,7 @@ static void sync_timeline_free(struct kref *kref) container_of(kref, struct sync_timeline, kref); sync_timeline_debug_remove(obj); + flush_work(&obj->signal_work); kfree(obj); } @@ -199,23 +202,20 @@ static const struct dma_fence_ops timeline_fence_ops = { /** * sync_timeline_signal() - signal a status change on a sync_timeline - * @obj: sync_timeline to signal - * @inc: num to increment on timeline->value + * @work: the work item * - * A sync implementation should call this any time one of it's fences - * has signaled or has an error condition. + * Signal all fences where the sequence number indicate to do so. */ -static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) +static void sync_timeline_signal(struct work_struct *work) { + struct sync_timeline *obj = container_of(work, typeof(*obj), + signal_work); LIST_HEAD(signalled); struct sync_pt *pt, *next; trace_sync_timeline(obj); spin_lock_irq(&obj->lock); - - obj->value += inc; - list_for_each_entry_safe(pt, next, &obj->pt_list, link) { if (!timeline_fence_signaled(&pt->base)) break; @@ -227,7 +227,6 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) dma_fence_signal_locked(&pt->base); } - spin_unlock_irq(&obj->lock); list_for_each_entry_safe(pt, next, &signalled, link) { @@ -394,11 +393,15 @@ static long sw_sync_ioctl_inc(struct sync_timeline *obj, unsigned long arg) return -EFAULT; while (value > INT_MAX) { - sync_timeline_signal(obj, INT_MAX); + obj->value += INT_MAX; + + schedule_work(&obj->signal_work); + flush_work(&obj->signal_work); value -= INT_MAX; } - sync_timeline_signal(obj, value); + obj->value += value; + schedule_work(&obj->signal_work); return 0; } diff --git a/drivers/dma-buf/sync_debug.h b/drivers/dma-buf/sync_debug.h index 02af347293d0..a1b03c48d82a 100644 --- a/drivers/dma-buf/sync_debug.h +++ b/drivers/dma-buf/sync_debug.h @@ -17,6 +17,7 @@ #include <linux/rbtree.h> #include <linux/spinlock.h> #include <linux/dma-fence.h> +#include <linux/workqueue.h> #include <linux/sync_file.h> #include <uapi/linux/sync_file.h> @@ -40,6 +41,7 @@ struct sync_timeline { struct rb_root pt_tree; struct list_head pt_list; + struct work_struct signal_work; spinlock_t lock; struct list_head sync_timeline_list; -- 2.43.0