diff options
Diffstat (limited to 'drivers/media/video/samsung/mali/linux/mali_dma_buf.c')
-rw-r--r-- | drivers/media/video/samsung/mali/linux/mali_dma_buf.c | 392 |
1 files changed, 0 insertions, 392 deletions
diff --git a/drivers/media/video/samsung/mali/linux/mali_dma_buf.c b/drivers/media/video/samsung/mali/linux/mali_dma_buf.c deleted file mode 100644 index 4dd711f..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_dma_buf.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -#include <linux/fs.h> /* file system operations */ -#include <asm/uaccess.h> /* user space access */ -#include <linux/dma-buf.h> -#include <linux/scatterlist.h> -#include <linux/rbtree.h> - -#include "mali_ukk.h" -#include "mali_osk.h" -#include "mali_kernel_common.h" -#include "mali_session.h" -#include "mali_kernel_linux.h" - -#include "mali_kernel_memory_engine.h" -#include "mali_memory.h" - -#include "mali_kernel_sysfs.h" - - -struct mali_dma_buf_attachment { - struct dma_buf *buf; - struct dma_buf_attachment *attachment; - struct sg_table *sgt; - _mali_osk_atomic_t ref; - struct rb_node rb_node; -}; - -static struct rb_root mali_dma_bufs = RB_ROOT; -static DEFINE_SPINLOCK(mali_dma_bufs_lock); - -static inline struct mali_dma_buf_attachment *mali_dma_buf_lookup(struct rb_root *root, struct dma_buf *target) -{ - struct rb_node *node = root->rb_node; - struct mali_dma_buf_attachment *res; - - spin_lock(&mali_dma_bufs_lock); - while (node) - { - res = rb_entry(node, struct mali_dma_buf_attachment, rb_node); - - if (target < res->buf) node = node->rb_left; - else if (target > res->buf) node = node->rb_right; - else - { - _mali_osk_atomic_inc(&res->ref); - spin_unlock(&mali_dma_bufs_lock); - return res; - } - } - spin_unlock(&mali_dma_bufs_lock); - - return NULL; -} - -static void mali_dma_buf_add(struct rb_root *root, struct mali_dma_buf_attachment *new) -{ - struct rb_node **node = &root->rb_node; - struct rb_node *parent = NULL; - struct mali_dma_buf_attachment *res; - - spin_lock(&mali_dma_bufs_lock); - while (*node) - { - parent = *node; - res = rb_entry(*node, struct mali_dma_buf_attachment, rb_node); - - if (new->buf < res->buf) node = &(*node)->rb_left; - else node = &(*node)->rb_right; - } - - rb_link_node(&new->rb_node, parent, node); - rb_insert_color(&new->rb_node, &mali_dma_bufs); - - spin_unlock(&mali_dma_bufs_lock); - - return; -} - - -static void mali_dma_buf_release(void *ctx, void *handle) -{ - struct mali_dma_buf_attachment *mem; - u32 ref; - - mem = (struct mali_dma_buf_attachment *)handle; - - MALI_DEBUG_ASSERT_POINTER(mem); - MALI_DEBUG_ASSERT_POINTER(mem->attachment); - MALI_DEBUG_ASSERT_POINTER(mem->buf); - - spin_lock(&mali_dma_bufs_lock); - ref = _mali_osk_atomic_dec_return(&mem->ref); - - MALI_DEBUG_ASSERT(ref >= 0); - - if (0 == ref) - { - rb_erase(&mem->rb_node, &mali_dma_bufs); - spin_unlock(&mali_dma_bufs_lock); - - MALI_DEBUG_ASSERT(0 == _mali_osk_atomic_read(&mem->ref)); - - dma_buf_unmap_attachment(mem->attachment, mem->sgt, DMA_BIDIRECTIONAL); - - dma_buf_detach(mem->buf, mem->attachment); - dma_buf_put(mem->buf); - - _mali_osk_free(mem); - } - else - { - spin_unlock(&mali_dma_bufs_lock); - } -} - -/* Callback from memory engine which will map into Mali virtual address space */ -static mali_physical_memory_allocation_result mali_dma_buf_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) -{ - struct mali_session_data *session; - struct mali_page_directory *pagedir; - struct mali_dma_buf_attachment *mem; - struct scatterlist *sg; - int i; - u32 virt; - - MALI_DEBUG_ASSERT_POINTER(ctx); - MALI_DEBUG_ASSERT_POINTER(engine); - MALI_DEBUG_ASSERT_POINTER(descriptor); - MALI_DEBUG_ASSERT_POINTER(offset); - MALI_DEBUG_ASSERT_POINTER(alloc_info); - - /* Mapping dma-buf with an offset is not supported. */ - MALI_DEBUG_ASSERT(0 == *offset); - - virt = descriptor->mali_address; - session = (struct mali_session_data *)descriptor->mali_addr_mapping_info; - pagedir = mali_session_get_page_directory(session); - - MALI_DEBUG_ASSERT_POINTER(session); - - mem = (struct mali_dma_buf_attachment *)ctx; - - MALI_DEBUG_ASSERT_POINTER(mem); - - mem->sgt = dma_buf_map_attachment(mem->attachment, DMA_BIDIRECTIONAL); - if (IS_ERR_OR_NULL(mem->sgt)) - { - MALI_PRINT_ERROR(("Failed to map dma-buf attachment\n")); - return MALI_MEM_ALLOC_INTERNAL_FAILURE; - } - - for_each_sg(mem->sgt->sgl, sg, mem->sgt->nents, i) - { - u32 size = sg_dma_len(sg); - dma_addr_t phys = sg_dma_address(sg); - - /* sg must be page aligned. */ - MALI_DEBUG_ASSERT(0 == size % MALI_MMU_PAGE_SIZE); - - mali_mmu_pagedir_update(pagedir, virt, phys, size, MALI_CACHE_STANDARD); - - virt += size; - *offset += size; - } - - if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE) - { - u32 guard_phys; - MALI_DEBUG_PRINT(7, ("Mapping in extra guard page\n")); - - guard_phys = sg_dma_address(mem->sgt->sgl); - mali_mmu_pagedir_update(mali_session_get_page_directory(session), virt, guard_phys, MALI_MMU_PAGE_SIZE, MALI_CACHE_STANDARD); - } - - MALI_DEBUG_ASSERT(*offset == descriptor->size); - - alloc_info->ctx = NULL; - alloc_info->handle = mem; - alloc_info->next = NULL; - alloc_info->release = mali_dma_buf_release; - - return MALI_MEM_ALLOC_FINISHED; -} - -int mali_attach_dma_buf(struct mali_session_data *session, _mali_uk_attach_dma_buf_s __user *user_arg) -{ - mali_physical_memory_allocator external_memory_allocator; - struct dma_buf *buf; - struct mali_dma_buf_attachment *mem; - _mali_uk_attach_dma_buf_s args; - mali_memory_allocation *descriptor; - int md; - int fd; - - /* Get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ - if (0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_attach_dma_buf_s))) - { - return -EFAULT; - } - - - fd = args.mem_fd; - - buf = dma_buf_get(fd); - if (IS_ERR_OR_NULL(buf)) - { - MALI_DEBUG_PRINT(2, ("Failed to get dma-buf from fd: %d\n", fd)); - return PTR_RET(buf); - } - - /* Currently, mapping of the full buffer are supported. */ - if (args.size != buf->size) - { - MALI_DEBUG_PRINT(2, ("dma-buf size doesn't match mapping size.\n")); - dma_buf_put(buf); - return -EINVAL; - } - - - mem = mali_dma_buf_lookup(&mali_dma_bufs, buf); - if (NULL == mem) - { - /* dma-buf is not already attached to Mali */ - mem = _mali_osk_calloc(1, sizeof(struct mali_dma_buf_attachment)); - if (NULL == mem) - { - MALI_PRINT_ERROR(("Failed to allocate dma-buf tracing struct\n")); - dma_buf_put(mem->buf); - return -ENOMEM; - } - _mali_osk_atomic_init(&mem->ref, 1); - mem->buf = buf; - - mem->attachment = dma_buf_attach(mem->buf, mali_device); - if (NULL == mem->attachment) - { - MALI_DEBUG_PRINT(2, ("Failed to attach to dma-buf %d\n", fd)); - dma_buf_put(mem->buf); - _mali_osk_free(mem); - return -EFAULT; - } - - mali_dma_buf_add(&mali_dma_bufs, mem); - } - else - { - /* dma-buf is already attached to Mali */ - /* Give back the reference we just took, mali_dma_buf_lookup grabbed a new reference for us. */ - dma_buf_put(buf); - } - - /* Map dma-buf into this session's page tables */ - - /* Set up Mali memory descriptor */ - descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation)); - if (NULL == descriptor) - { - MALI_PRINT_ERROR(("Failed to allocate descriptor dma-buf %d\n", fd)); - mali_dma_buf_release(NULL, mem); - return -ENOMEM; - } - - descriptor->size = args.size; - descriptor->mapping = NULL; - descriptor->mali_address = args.mali_address; - descriptor->mali_addr_mapping_info = (void*)session; - descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */ - descriptor->lock = session->memory_lock; - - if (args.flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) - { - descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE; - } - _mali_osk_list_init( &descriptor->list ); - - /* Get descriptor mapping for memory. */ - if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session->descriptor_mapping, descriptor, &md)) - { - MALI_PRINT_ERROR(("Failed to create descriptor mapping for dma-buf %d\n", fd)); - _mali_osk_free(descriptor); - mali_dma_buf_release(NULL, mem); - return -EFAULT; - } - - external_memory_allocator.allocate = mali_dma_buf_commit; - external_memory_allocator.allocate_page_table_block = NULL; - external_memory_allocator.ctx = mem; - external_memory_allocator.name = "DMA-BUF Memory"; - external_memory_allocator.next = NULL; - - /* Map memory into session's Mali virtual address space. */ - _mali_osk_lock_wait(session->memory_lock, _MALI_OSK_LOCKMODE_RW); - if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(mali_mem_get_memory_engine(), descriptor, &external_memory_allocator, NULL)) - { - _mali_osk_lock_signal(session->memory_lock, _MALI_OSK_LOCKMODE_RW); - - MALI_PRINT_ERROR(("Failed to map dma-buf %d into Mali address space\n", fd)); - mali_descriptor_mapping_free(session->descriptor_mapping, md); - mali_dma_buf_release(NULL, mem); - return -ENOMEM; - } - _mali_osk_lock_signal(session->memory_lock, _MALI_OSK_LOCKMODE_RW); - - /* Return stuff to user space */ - if (0 != put_user(md, &user_arg->cookie)) - { - /* Roll back */ - MALI_PRINT_ERROR(("Failed to return descriptor to user space for dma-buf %d\n", fd)); - mali_descriptor_mapping_free(session->descriptor_mapping, md); - mali_dma_buf_release(NULL, mem); - return -EFAULT; - } - - return 0; -} - -int mali_release_dma_buf(struct mali_session_data *session, _mali_uk_release_dma_buf_s __user *user_arg) -{ - _mali_uk_release_dma_buf_s args; - mali_memory_allocation *descriptor; - - /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ - if ( 0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_release_dma_buf_s)) ) - { - return -EFAULT; - } - - if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session->descriptor_mapping, args.cookie, (void**)&descriptor)) - { - MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to release dma-buf\n", args.cookie)); - return -EINVAL; - } - - descriptor = mali_descriptor_mapping_free(session->descriptor_mapping, args.cookie); - - if (NULL != descriptor) - { - _mali_osk_lock_wait( session->memory_lock, _MALI_OSK_LOCKMODE_RW ); - - /* Will call back to mali_dma_buf_release() which will release the dma-buf attachment. */ - mali_allocation_engine_release_memory(mali_mem_get_memory_engine(), descriptor); - - _mali_osk_lock_signal( session->memory_lock, _MALI_OSK_LOCKMODE_RW ); - - _mali_osk_free(descriptor); - } - - /* Return the error that _mali_ukk_map_external_ump_mem produced */ - return 0; -} - -int mali_dma_buf_get_size(struct mali_session_data *session, _mali_uk_dma_buf_get_size_s __user *user_arg) -{ - _mali_uk_dma_buf_get_size_s args; - int fd; - struct dma_buf *buf; - - /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ - if ( 0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_dma_buf_get_size_s)) ) - { - return -EFAULT; - } - - /* Do DMA-BUF stuff */ - fd = args.mem_fd; - - buf = dma_buf_get(fd); - if (IS_ERR_OR_NULL(buf)) - { - MALI_DEBUG_PRINT(2, ("Failed to get dma-buf from fd: %d\n", fd)); - return PTR_RET(buf); - } - - if (0 != put_user(buf->size, &user_arg->size)) - { - dma_buf_put(buf); - return -EFAULT; - } - - dma_buf_put(buf); - - return 0; -} |