| /* |
| * Copyright (C) 2012-2013 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_sync_user.c |
| * |
| */ |
| |
| #ifdef CONFIG_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 <asm/uaccess.h> |
| |
| #include "mali_osk.h" |
| #include "mali_kernel_common.h" |
| #include "mali_sync.h" |
| |
| static int mali_stream_close(struct inode * inode, struct file * file) |
| { |
| struct sync_timeline * tl; |
| tl = (struct sync_timeline*)file->private_data; |
| BUG_ON(!tl); |
| sync_timeline_destroy(tl); |
| return 0; |
| } |
| |
| static struct file_operations stream_fops = |
| { |
| .owner = THIS_MODULE, |
| .release = mali_stream_close, |
| }; |
| |
| _mali_osk_errcode_t mali_stream_create(const char * name, int *out_fd) |
| { |
| struct sync_timeline * tl; |
| BUG_ON(!out_fd); |
| |
| tl = mali_sync_timeline_alloc(name); |
| if (!tl) |
| { |
| return _MALI_OSK_ERR_FAULT; |
| } |
| |
| *out_fd = anon_inode_getfd(name, &stream_fops, tl, O_RDONLY | O_CLOEXEC); |
| |
| if (*out_fd < 0) |
| { |
| sync_timeline_destroy(tl); |
| return _MALI_OSK_ERR_FAULT; |
| } |
| else |
| { |
| return _MALI_OSK_ERR_OK; |
| } |
| } |
| |
| static mali_sync_pt *mali_stream_create_point_internal(int tl_fd, mali_bool timed) |
| { |
| struct sync_timeline *tl; |
| struct sync_pt * pt; |
| struct file *tl_file; |
| |
| tl_file = fget(tl_fd); |
| if (tl_file == NULL) |
| return NULL; |
| |
| if (tl_file->f_op != &stream_fops) |
| { |
| pt = NULL; |
| goto out; |
| } |
| |
| tl = tl_file->private_data; |
| |
| if (unlikely(timed)) |
| { |
| pt = mali_sync_timed_pt_alloc(tl); |
| } |
| else |
| { |
| pt = mali_sync_pt_alloc(tl); |
| } |
| |
| if (!pt) |
| { |
| pt = NULL; |
| goto out; |
| } |
| |
| out: |
| fput(tl_file); |
| |
| return pt; |
| } |
| |
| mali_sync_pt *mali_stream_create_point(int tl_fd) |
| { |
| return mali_stream_create_point_internal(tl_fd, MALI_FALSE); |
| } |
| |
| int mali_stream_create_fence(mali_sync_pt *pt) |
| { |
| struct sync_fence *fence; |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) |
| struct fdtable * fdt; |
| struct files_struct * files; |
| #endif |
| int fd = -1; |
| |
| fence = sync_fence_create("mali_fence", pt); |
| if (!fence) |
| { |
| sync_pt_free(pt); |
| fd = -EFAULT; |
| goto out; |
| } |
| |
| /* create a fd representing the fence */ |
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) |
| fd = get_unused_fd_flags(O_CLOEXEC); |
| if (fd < 0) |
| { |
| sync_fence_put(fence); |
| goto out; |
| } |
| #else |
| fd = get_unused_fd(); |
| if (fd < 0) |
| { |
| sync_fence_put(fence); |
| goto out; |
| } |
| |
| files = current->files; |
| spin_lock(&files->file_lock); |
| fdt = files_fdtable(files); |
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) |
| __set_close_on_exec(fd, fdt); |
| #else |
| FD_SET(fd, fdt->close_on_exec); |
| #endif /* Linux >= 3.4 */ |
| spin_unlock(&files->file_lock); |
| #endif /* Linux >= 3.6 */ |
| |
| /* bind fence to the new fd */ |
| sync_fence_install(fence, fd); |
| |
| out: |
| return fd; |
| } |
| |
| int mali_stream_create_empty_fence(int tl_fd) |
| { |
| int fd; |
| mali_sync_pt *pt; |
| |
| pt = mali_stream_create_point_internal(tl_fd, MALI_TRUE); |
| |
| if (NULL == pt) return -ENOMEM; |
| |
| fd = mali_stream_create_fence(pt); |
| |
| return fd; |
| } |
| |
| _mali_osk_errcode_t mali_fence_validate(int fd) |
| { |
| struct sync_fence * fence; |
| fence = sync_fence_fdget(fd); |
| if (NULL != fence) |
| { |
| sync_fence_put(fence); |
| return _MALI_OSK_ERR_OK; |
| } |
| else |
| { |
| return _MALI_OSK_ERR_FAULT; |
| } |
| } |
| |
| #endif /* CONFIG_SYNC */ |