| /* |
| * Copyright (C) 2010-2014, 2016 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_osk_low_level_mem.c |
| * Implementation of the OS abstraction layer for the kernel device driver |
| */ |
| |
| #include <asm/io.h> |
| #include <linux/ioport.h> |
| #include <linux/slab.h> |
| |
| #include "mali_kernel_common.h" |
| #include "mali_osk.h" |
| #include "mali_ukk.h" |
| |
| void _mali_osk_mem_barrier(void) |
| { |
| mb(); |
| } |
| |
| void _mali_osk_write_mem_barrier(void) |
| { |
| wmb(); |
| } |
| |
| mali_io_address _mali_osk_mem_mapioregion(uintptr_t phys, u32 size, const char *description) |
| { |
| return (mali_io_address)ioremap_nocache(phys, size); |
| } |
| |
| void _mali_osk_mem_unmapioregion(uintptr_t phys, u32 size, mali_io_address virt) |
| { |
| iounmap((void *)virt); |
| } |
| |
| _mali_osk_errcode_t inline _mali_osk_mem_reqregion(uintptr_t phys, u32 size, const char *description) |
| { |
| #if MALI_LICENSE_IS_GPL |
| return _MALI_OSK_ERR_OK; /* GPL driver gets the mem region for the resources registered automatically */ |
| #else |
| return ((NULL == request_mem_region(phys, size, description)) ? _MALI_OSK_ERR_NOMEM : _MALI_OSK_ERR_OK); |
| #endif |
| } |
| |
| void inline _mali_osk_mem_unreqregion(uintptr_t phys, u32 size) |
| { |
| #if !MALI_LICENSE_IS_GPL |
| release_mem_region(phys, size); |
| #endif |
| } |
| |
| void inline _mali_osk_mem_iowrite32_relaxed(volatile mali_io_address addr, u32 offset, u32 val) |
| { |
| __raw_writel(cpu_to_le32(val), ((u8 *)addr) + offset); |
| } |
| |
| u32 inline _mali_osk_mem_ioread32(volatile mali_io_address addr, u32 offset) |
| { |
| return ioread32(((u8 *)addr) + offset); |
| } |
| |
| void inline _mali_osk_mem_iowrite32(volatile mali_io_address addr, u32 offset, u32 val) |
| { |
| iowrite32(val, ((u8 *)addr) + offset); |
| } |
| |
| void _mali_osk_cache_flushall(void) |
| { |
| /** @note Cached memory is not currently supported in this implementation */ |
| } |
| |
| void _mali_osk_cache_ensure_uncached_range_flushed(void *uncached_mapping, u32 offset, u32 size) |
| { |
| _mali_osk_write_mem_barrier(); |
| } |
| |
| u32 _mali_osk_mem_write_safe(void __user *dest, const void __user *src, u32 size) |
| { |
| #define MALI_MEM_SAFE_COPY_BLOCK_SIZE 4096 |
| u32 retval = 0; |
| void *temp_buf; |
| |
| temp_buf = kmalloc(MALI_MEM_SAFE_COPY_BLOCK_SIZE, GFP_KERNEL); |
| if (NULL != temp_buf) { |
| u32 bytes_left_to_copy = size; |
| u32 i; |
| for (i = 0; i < size; i += MALI_MEM_SAFE_COPY_BLOCK_SIZE) { |
| u32 size_to_copy; |
| u32 size_copied; |
| u32 bytes_left; |
| |
| if (bytes_left_to_copy > MALI_MEM_SAFE_COPY_BLOCK_SIZE) { |
| size_to_copy = MALI_MEM_SAFE_COPY_BLOCK_SIZE; |
| } else { |
| size_to_copy = bytes_left_to_copy; |
| } |
| |
| bytes_left = copy_from_user(temp_buf, ((char *)src) + i, size_to_copy); |
| size_copied = size_to_copy - bytes_left; |
| |
| bytes_left = copy_to_user(((char *)dest) + i, temp_buf, size_copied); |
| size_copied -= bytes_left; |
| |
| bytes_left_to_copy -= size_copied; |
| retval += size_copied; |
| |
| if (size_copied != size_to_copy) { |
| break; /* Early out, we was not able to copy this entire block */ |
| } |
| } |
| |
| kfree(temp_buf); |
| } |
| |
| return retval; |
| } |
| |
| _mali_osk_errcode_t _mali_ukk_mem_write_safe(_mali_uk_mem_write_safe_s *args) |
| { |
| void __user *src; |
| void __user *dst; |
| struct mali_session_data *session; |
| |
| MALI_DEBUG_ASSERT_POINTER(args); |
| |
| session = (struct mali_session_data *)(uintptr_t)args->ctx; |
| |
| if (NULL == session) { |
| return _MALI_OSK_ERR_INVALID_ARGS; |
| } |
| |
| src = (void __user *)(uintptr_t)args->src; |
| dst = (void __user *)(uintptr_t)args->dest; |
| |
| /* Return number of bytes actually copied */ |
| args->size = _mali_osk_mem_write_safe(dst, src, args->size); |
| return _MALI_OSK_ERR_OK; |
| } |