blob: ee5bfc9eba75018ff7b09a1ef96be0d7fe30a5df [file] [log] [blame]
/*
*
* (C) COPYRIGHT 2012-2015 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation, and any use by you of this program is subject to the terms
* of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained
* from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
/**
* @file mali_kbase_sync_user.c
*
*/
#ifdef CONFIG_SW_SYNC
#include <linux/sched.h>
#include <linux/fdtable.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/anon_inodes.h>
#include <linux/version.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <mali_kbase_sync.h>
#include <mali_base_kernel_sync.h>
static int kbase_stream_close(struct inode *inode, struct file *file)
{
struct mali_sync_context *msc;
msc = (struct mali_sync_context *)file->private_data;
BUG_ON(!msc);
kbase_sync_context_free(msc);
return 0;
}
static const struct file_operations stream_fops = {
.owner = THIS_MODULE,
.release = kbase_stream_close,
};
int kbase_stream_create(const char *name, int *const out_fd)
{
struct mali_sync_context *msc;
BUG_ON(!out_fd);
msc = kbase_sync_context_alloc(name);
if (!msc)
return -EINVAL;
*out_fd = anon_inode_getfd(name, &stream_fops, msc, O_RDONLY | O_CLOEXEC);
if (*out_fd < 0) {
kbase_sync_context_free(msc);
return -EINVAL;
}
return 0;
}
int kbase_stream_create_fence(int tl_fd, struct sync_file **rsfile)
{
struct mali_sync_context *msc;
struct dma_fence *fence;
struct sync_file *sfile;
int fd;
struct file *tl_file;
tl_file = fget(tl_fd);
if (tl_file == NULL)
return -EBADF;
if (tl_file->f_op != &stream_fops) {
fd = -EBADF;
goto out;
}
msc = tl_file->private_data;
fence = kbase_fence_alloc(msc);
if (!fence) {
fd = -EFAULT;
goto out;
}
sfile = sync_file_create(fence);
if (!sfile) {
dma_fence_put(fence);
fd = -EFAULT;
goto out;
}
/* Unref the fence from here, let the sync_file own it */
dma_fence_put(fence);
/* create a fd representing the fence */
fd = get_unused_fd_flags(O_RDWR | O_CLOEXEC);
if (fd < 0) {
fput(sfile->file);
goto out;
}
/* bind fence to the new fd */
fd_install(fd, sfile->file);
/* Return newly created sync_file to caller. */
fget(fd);
*rsfile = sfile;
out:
fput(tl_file);
return fd;
}
int kbase_fence_validate(int fd)
{
struct dma_fence *fence = sync_file_get_fence(fd);
if (!fence)
return -EINVAL;
dma_fence_put(fence);
return 0;
}
#endif /* CONFIG_SW_SYNC */