From: Dave Airlie <airlied@xxxxxxxxxx> Using sync_file to back vulkan semaphores means need to replace the fence underlying the sync file. This replace function removes the callback, swaps the fence, and returns the old one. This also exports the alloc and fdget functionality for the semaphore wrapper code. v2: use rcu. Signed-off-by: Dave Airlie <airlied at redhat.com> --- drivers/dma-buf/sync_file.c | 42 ++++++++++++++++++++++++++++++++++++++++-- include/linux/sync_file.h | 5 ++++- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index dcba931..d826066 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -32,7 +32,14 @@ static const struct file_operations sync_file_fops; #define sync_file_assert_held(obj) \ lockdep_assert_held(&(obj)->lock) -static struct sync_file *sync_file_alloc(void) +/** + * sync_file_alloc() - allocate an unfenced sync file + * + * Creates a sync_file. + * The sync_file can be released with fput(sync_file->file). + * Returns the sync_file or NULL in case of error. + */ +struct sync_file *sync_file_alloc(void) { struct sync_file *sync_file; @@ -60,6 +67,7 @@ static struct sync_file *sync_file_alloc(void) kfree(sync_file); return NULL; } +EXPORT_SYMBOL(sync_file_alloc); static void fence_check_cb_func(struct dma_fence *f, struct dma_fence_cb *cb) { @@ -100,7 +108,7 @@ struct sync_file *sync_file_create(struct dma_fence *fence) } EXPORT_SYMBOL(sync_file_create); -static struct sync_file *sync_file_fdget(int fd) +struct sync_file *sync_file_fdget(int fd) { struct file *file = fget(fd); @@ -116,6 +124,7 @@ static struct sync_file *sync_file_fdget(int fd) fput(file); return NULL; } +EXPORT_SYMBOL(sync_file_fdget); /** * sync_file_get_fence - get the fence related to the sync_file fd @@ -153,6 +162,35 @@ sync_file_get_fence_locked(struct sync_file *sync_file) sync_file_held(sync_file)); } +/** + * sync_file_replace_fence - replace the fence related to the sync_file + * @sync_file: sync file to replace fence in + * @fence: fence to replace with (or NULL for no fence). + * Returns previous fence. + */ +struct dma_fence *sync_file_replace_fence(struct sync_file *sync_file, + struct dma_fence *fence) +{ + struct dma_fence *ret_fence = NULL; + + if (fence) + dma_fence_get(fence); + + mutex_lock(&sync_file->lock); + + ret_fence = sync_file_get_fence_locked(sync_file); + if (ret_fence) { + if (test_bit(POLL_ENABLED, &ret_fence->flags)) + dma_fence_remove_callback(ret_fence, &sync_file->cb); + } + + RCU_INIT_POINTER(sync_file->fence, fence); + + mutex_unlock(&sync_file->lock); + return ret_fence; +} +EXPORT_SYMBOL(sync_file_replace_fence); + static int sync_file_set_fence(struct sync_file *sync_file, struct dma_fence **fences, int num_fences) { diff --git a/include/linux/sync_file.h b/include/linux/sync_file.h index 006412f..555ae99 100644 --- a/include/linux/sync_file.h +++ b/include/linux/sync_file.h @@ -50,7 +50,10 @@ struct sync_file { #define POLL_ENABLED DMA_FENCE_FLAG_USER_BITS +struct sync_file *sync_file_alloc(void); struct sync_file *sync_file_create(struct dma_fence *fence); struct dma_fence *sync_file_get_fence(int fd); - +struct sync_file *sync_file_fdget(int fd); +struct dma_fence *sync_file_replace_fence(struct sync_file *sync_file, + struct dma_fence *fence); #endif /* _LINUX_SYNC_H */ -- 2.7.4