Patchwork [2/2] dma-buf/sw_sync: force signal all unsignaled fences on dying timeline

login
register
mail settings
Submitter Gustavo F. Padovan
Date Sept. 4, 2017, 11:06 p.m.
Message ID <20170904230604.12757-2-gustavo@padovan.org>
Download mbox | patch
Permalink /patch/9937637/
State New
Headers show

Comments

Gustavo F. Padovan - Sept. 4, 2017, 11:06 p.m.
From: Dominik Behr <dbehr@chromium.org>

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.

Signed-off-by: Dominik Behr <dbehr@chromium.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
---
 drivers/dma-buf/sw_sync.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
Chris Wilson - Sept. 4, 2017, 11:53 p.m.
Quoting Gustavo Padovan (2017-09-05 00:06:04)
> From: Dominik Behr <dbehr@chromium.org>
> 
> 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.
> 
> Signed-off-by: Dominik Behr <dbehr@chromium.org>
> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
> ---
>  drivers/dma-buf/sw_sync.c | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
> index 38cc7389a6c1..a85198c75a1b 100644
> --- a/drivers/dma-buf/sw_sync.c
> +++ b/drivers/dma-buf/sw_sync.c
> @@ -321,9 +321,21 @@ static int sw_sync_debugfs_open(struct inode *inode, struct file *file)
>  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) {
> +               dma_fence_set_error(&pt->base, -ENOENT);
> +               dma_fence_signal_locked(&pt->base);
> +               list_del_init(&pt->link);
> +               rb_erase(&pt->node, &obj->pt_tree);

Since the timeline is dead, we don't need to worry about trimming the
completed signals from the timeline. No need for the
list_del/rb_erase here, especially considering the trickiness required
to avoid the potential deadlock which is missing here.
-Chris

Patch

diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
index 38cc7389a6c1..a85198c75a1b 100644
--- a/drivers/dma-buf/sw_sync.c
+++ b/drivers/dma-buf/sw_sync.c
@@ -321,9 +321,21 @@  static int sw_sync_debugfs_open(struct inode *inode, struct file *file)
 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) {
+		dma_fence_set_error(&pt->base, -ENOENT);
+		dma_fence_signal_locked(&pt->base);
+		list_del_init(&pt->link);
+		rb_erase(&pt->node, &obj->pt_tree);
+	}
+
+	spin_unlock_irq(&obj->lock);
+
 	sync_timeline_put(obj);
 	return 0;
 }