summaryrefslogtreecommitdiffstats
path: root/drivers/staging/android/sync.c
diff options
context:
space:
mode:
authorErik Gilling2013-03-01 01:43:05 +0100
committerGreg Kroah-Hartman2013-03-04 10:40:09 +0100
commitc0f61a4e6145728153d0b94152b4dd5b06899b3b (patch)
tree6e9d346a5ccc15a19469e3d82e2c21e5ebac7fe2 /drivers/staging/android/sync.c
parentstaging: sync: Add poll support (diff)
downloadkernel-qcow2-linux-c0f61a4e6145728153d0b94152b4dd5b06899b3b.tar.gz
kernel-qcow2-linux-c0f61a4e6145728153d0b94152b4dd5b06899b3b.tar.xz
kernel-qcow2-linux-c0f61a4e6145728153d0b94152b4dd5b06899b3b.zip
staging: sync: Allow async waits to be canceled
In order to allow drivers to cleanly handled teardown we need to allow them to cancel pending async waits. To do this cleanly, we move allocation of sync_fence_waiter to the driver calling sync_async_wait(). Cc: Maarten Lankhorst <maarten.lankhorst@canonical.com> Cc: Erik Gilling <konkers@android.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Rob Clark <robclark@gmail.com> Cc: Sumit Semwal <sumit.semwal@linaro.org> Cc: dri-devel@lists.freedesktop.org Cc: Android Kernel Team <kernel-team@android.com> Signed-off-by: Erik Gilling <konkers@android.com> Signed-off-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/android/sync.c')
-rw-r--r--drivers/staging/android/sync.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c
index 9e35ea3e73da..54f84d926b9a 100644
--- a/drivers/staging/android/sync.c
+++ b/drivers/staging/android/sync.c
@@ -421,33 +421,22 @@ static void sync_fence_signal_pt(struct sync_pt *pt)
container_of(pos, struct sync_fence_waiter,
waiter_list);
- waiter->callback(fence, waiter->callback_data);
list_del(pos);
- kfree(waiter);
+ waiter->callback(fence, waiter);
}
wake_up(&fence->wq);
}
}
int sync_fence_wait_async(struct sync_fence *fence,
- void (*callback)(struct sync_fence *, void *data),
- void *callback_data)
+ struct sync_fence_waiter *waiter)
{
- struct sync_fence_waiter *waiter;
unsigned long flags;
int err = 0;
- waiter = kzalloc(sizeof(struct sync_fence_waiter), GFP_KERNEL);
- if (waiter == NULL)
- return -ENOMEM;
-
- waiter->callback = callback;
- waiter->callback_data = callback_data;
-
spin_lock_irqsave(&fence->waiter_list_lock, flags);
if (fence->status) {
- kfree(waiter);
err = fence->status;
goto out;
}
@@ -459,6 +448,34 @@ out:
return err;
}
+int sync_fence_cancel_async(struct sync_fence *fence,
+ struct sync_fence_waiter *waiter)
+{
+ struct list_head *pos;
+ struct list_head *n;
+ unsigned long flags;
+ int ret = -ENOENT;
+
+ spin_lock_irqsave(&fence->waiter_list_lock, flags);
+ /*
+ * Make sure waiter is still in waiter_list because it is possible for
+ * the waiter to be removed from the list while the callback is still
+ * pending.
+ */
+ list_for_each_safe(pos, n, &fence->waiter_list_head) {
+ struct sync_fence_waiter *list_waiter =
+ container_of(pos, struct sync_fence_waiter,
+ waiter_list);
+ if (list_waiter == waiter) {
+ list_del(pos);
+ ret = 0;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&fence->waiter_list_lock, flags);
+ return ret;
+}
+
int sync_fence_wait(struct sync_fence *fence, long timeout)
{
int err;
@@ -739,8 +756,7 @@ static void sync_print_fence(struct seq_file *s, struct sync_fence *fence)
container_of(pos, struct sync_fence_waiter,
waiter_list);
- seq_printf(s, "waiter %pF %p\n", waiter->callback,
- waiter->callback_data);
+ seq_printf(s, "waiter %pF\n", waiter->callback);
}
spin_unlock_irqrestore(&fence->waiter_list_lock, flags);
}