From df9d8c41ac73d51e7a3be1aacd4283467388701e Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 8 Sep 2015 17:30:52 -0700 Subject: [PATCH] CHROMIUM: dma-buf: dma-fence: fix warning when releasing active sync point Userspace can close the sync device while there are still active fence points, in which case kernel produces the following warning: [ 43.853176] ------------[ cut here ]------------ [ 43.857834] WARNING: CPU: 0 PID: 892 at /mnt/host/source/src/third_party/kernel/v3.18/drivers/staging/android/sync.c:439 android_fence_release+0x88/0x104() [ 43.871741] CPU: 0 PID: 892 Comm: Binder_5 Tainted: G U 3.18.0-07661-g0550ce9 #1 [ 43.880176] Hardware name: Google Tegra210 Smaug Rev 1+ (DT) [ 43.885834] Call trace: [ 43.888294] [] dump_backtrace+0x0/0x10c [ 43.893697] [] show_stack+0x10/0x1c [ 43.898756] [] dump_stack+0x74/0xb8 [ 43.903814] [] warn_slowpath_common+0x84/0xb0 [ 43.909736] [] warn_slowpath_null+0x14/0x20 [ 43.915482] [] android_fence_release+0x84/0x104 [ 43.921582] [] fence_release+0x104/0x134 [ 43.927066] [] sync_fence_free+0x74/0x9c [ 43.932552] [] sync_fence_release+0x34/0x48 [ 43.938304] [] __fput+0x100/0x1b8 [ 43.943185] [] ____fput+0x8/0x14 [ 43.947982] [] task_work_run+0xb0/0xe4 [ 43.953297] [] do_notify_resume+0x44/0x5c [ 43.958867] ---[ end trace 5a2aa4027cc5d171 ]--- Let's fix it by introducing a new optional callback (disable_signaling) to fence operations so that drivers can do proper clean ups when we remove last callback for given fence. BUG=chrome-os-partner:40303 TEST=Boot Smaug and observe that warning is gone. Change-Id: I05c34dcf74438c28405438c7ead0706b1f810fff Signed-off-by: Dmitry Torokhov Reviewed-on: https://chromium-review.googlesource.com/303409 Reviewed-by: Andrew Bresticker [AmitP: Refactored original changes by aligning with upstream naming convention and by using dma_fence_to_sync_pt() helper instead of container_of(). Also folded following android-4.9 changes into this patch fb66dc2a6e5e ("ANDROID: dma-buf/sw_sync: Rename active_list to link")]. Signed-off-by: Amit Pundir --- drivers/dma-buf/dma-fence.c | 6 +++++- drivers/dma-buf/sw_sync.c | 8 ++++++++ include/linux/dma-fence.h | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c index 9a302799040e..33ea68b45654 100644 --- a/drivers/dma-buf/dma-fence.c +++ b/drivers/dma-buf/dma-fence.c @@ -329,8 +329,12 @@ dma_fence_remove_callback(struct dma_fence *fence, struct dma_fence_cb *cb) spin_lock_irqsave(fence->lock, flags); ret = !list_empty(&cb->node); - if (ret) + if (ret) { list_del_init(&cb->node); + if (list_empty(&fence->cb_list)) + if (fence->ops->disable_signaling) + fence->ops->disable_signaling(fence); + } spin_unlock_irqrestore(fence->lock, flags); diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index 38cc7389a6c1..bf6638049c7d 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -169,6 +169,13 @@ static bool timeline_fence_enable_signaling(struct dma_fence *fence) return true; } +static void timeline_fence_disable_signaling(struct dma_fence *fence) +{ + struct sync_pt *pt = dma_fence_to_sync_pt(fence); + + list_del_init(&pt->link); +} + static void timeline_fence_value_str(struct dma_fence *fence, char *str, int size) { @@ -187,6 +194,7 @@ static const struct dma_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, + .disable_signaling = timeline_fence_disable_signaling, .signaled = timeline_fence_signaled, .wait = dma_fence_default_wait, .release = timeline_fence_release, diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h index 171895072435..6385ecd03155 100644 --- a/include/linux/dma-fence.h +++ b/include/linux/dma-fence.h @@ -111,6 +111,7 @@ struct dma_fence_cb { * @get_driver_name: returns the driver name. * @get_timeline_name: return the name of the context this fence belongs to. * @enable_signaling: enable software signaling of fence. + * @disable_signaling: disable software signaling of fence (optional). * @signaled: [optional] peek whether the fence is signaled, can be null. * @wait: custom wait implementation, or dma_fence_default_wait. * @release: [optional] called on destruction of fence, can be null @@ -170,6 +171,7 @@ struct dma_fence_ops { const char * (*get_driver_name)(struct dma_fence *fence); const char * (*get_timeline_name)(struct dma_fence *fence); bool (*enable_signaling)(struct dma_fence *fence); + void (*disable_signaling)(struct dma_fence *fence); bool (*signaled)(struct dma_fence *fence); signed long (*wait)(struct dma_fence *fence, bool intr, signed long timeout); -- 2.20.1