diff options
Diffstat (limited to 'drivers/media/video/samsung/ump')
19 files changed, 639 insertions, 44 deletions
diff --git a/drivers/media/video/samsung/ump/Kconfig b/drivers/media/video/samsung/ump/Kconfig index aaae26e..9d8e5e6 100644 --- a/drivers/media/video/samsung/ump/Kconfig +++ b/drivers/media/video/samsung/ump/Kconfig @@ -17,10 +17,18 @@ config UMP_VCM_ALLOC help Use VCM(virtual-contiguous-memory) to allocate physical memory. + +config UMP_R3P1_LSI + bool "Uses the R3P1 as a ump module" + depends on VIDEO_UMP + default n + ---help--- + This uses the r3p1 as a UMP kernel module + choice depends on VIDEO_UMP prompt "UMP MEMEMORY OPTION" -default UMP_OSMEM_ONLY +default UMP_OSMEM_ONLY config UMP_DED_ONLY bool "ump dedicated memory only" ---help--- @@ -37,7 +45,7 @@ config UMP_VCM_ONLY endchoice config UMP_MEM_SIZE int "UMP Memory Size" - depends on VIDEO_UMP + depends on VIDEO_UMP default "512" ---help--- This value is dedicated memory size of UMP (unit is MByte). @@ -48,4 +56,3 @@ config VIDEO_UMP_DEBUG default n help This enables UMP driver debug messages. - diff --git a/drivers/media/video/samsung/ump/Makefile b/drivers/media/video/samsung/ump/Makefile index 0ba1253..3a1aac0 100644 --- a/drivers/media/video/samsung/ump/Makefile +++ b/drivers/media/video/samsung/ump/Makefile @@ -18,6 +18,12 @@ UMP_MEM_SIZE= $(CONFIG_UMP_MEM_SIZE) USING_MEMORY=1 endif +ifeq ($(CONFIG_UMP_VCM_ONLY),y) +UMP_MEM_SIZE= $(CONFIG_UMP_MEM_SIZE) +USING_MEMORY=2 +endif + + # For UMP Debug ifeq ($(CONFIG_VIDEO_UMP_DEBUG),y) DEFINES += -DDEBUG @@ -72,6 +78,9 @@ ump-y := \ $(KBUILDROOT)common/ump_kernel_ref_drv.o\ $(OSKFILES) +ump-$(CONFIG_UMP_VCM_ALLOC) += \ + $(KBUILDROOT)linux/ump_kernel_memory_backend_vcm.o \ + EXTRA_CFLAGS += $(INCLUDES) \ $(DEFINES) diff --git a/drivers/media/video/samsung/ump/Makefile.common b/drivers/media/video/samsung/ump/Makefile.common index 503a38d..26a3d6c 100644 --- a/drivers/media/video/samsung/ump/Makefile.common +++ b/drivers/media/video/samsung/ump/Makefile.common @@ -1,9 +1,9 @@ # # Copyright (C) 2010-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. # diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_api.c b/drivers/media/video/samsung/ump/common/ump_kernel_api.c index 6569b02..83f0d30 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_api.c +++ b/drivers/media/video/samsung/ump/common/ump_kernel_api.c @@ -1,9 +1,9 @@ /* * Copyright (C) 2010-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. */ @@ -55,7 +55,24 @@ UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_secure_id(ump_secu return (ump_dd_handle)mem; } +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get(ump_secure_id secure_id) +{ + ump_dd_mem * mem; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + DBG_MSG(5, ("Getting handle from secure ID. ID: %u\n", secure_id)); + if (0 != ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Secure ID not found. ID: %u\n", secure_id)); + return UMP_DD_HANDLE_INVALID; + } + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + return (ump_dd_handle)mem; +} UMP_KERNEL_API_EXPORT unsigned long ump_dd_phys_block_count_get(ump_dd_handle memh) { @@ -260,7 +277,7 @@ _mali_osk_errcode_t _ump_ukk_release( _ump_uk_release_s *release_info ) } _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); - DBG_MSG_IF(1, _MALI_OSK_ERR_OK != ret, ("UMP memory with ID %u does not belong to this session.\n", secure_id)); + DBG_MSG_IF(1, _MALI_OSK_ERR_OK != ret, ("UMP memory with ID %u does not belong to this session.\n", secure_id)); DBG_MSG(4, ("_ump_ukk_release() returning 0x%x\n", ret)); return ret; diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_common.c b/drivers/media/video/samsung/ump/common/ump_kernel_common.c index b1545e8..a27bc77 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_common.c +++ b/drivers/media/video/samsung/ump/common/ump_kernel_common.c @@ -233,7 +233,12 @@ _mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args ) MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n")); return _MALI_OSK_ERR_INVALID_ARGS; } - + /* SEC kernel stability 2012-02-17 */ + if (NULL == session_data->cookies_map) + { + MSG_ERR(("session_data->cookies_map is NULL in _ump_ukk_map_mem()\n")); + return _MALI_OSK_ERR_INVALID_ARGS; + } descriptor = (ump_memory_allocation*) _mali_osk_calloc( 1, sizeof(ump_memory_allocation)); if (NULL == descriptor) { @@ -283,6 +288,12 @@ _mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args ) args->is_cached = 1; DBG_MSG(3, ("Mapping UMP secure_id: %d as cached.\n", args->secure_id)); } + else if ( args->is_cached) + { + mem->is_cached = 1; + descriptor->is_cached = 1; + DBG_MSG(3, ("Warning mapping UMP secure_id: %d. As cached, while it was allocated uncached.\n", args->secure_id)); + } else { descriptor->is_cached = 0; @@ -360,7 +371,12 @@ void _ump_ukk_unmap_mem( _ump_uk_unmap_mem_s *args ) MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n")); return; } - + /* SEC kernel stability 2012-02-17 */ + if (NULL == session_data->cookies_map) + { + MSG_ERR(("session_data->cookies_map is NULL in _ump_ukk_map_mem()\n")); + return; + } if (0 != ump_descriptor_mapping_get( session_data->cookies_map, (int)args->cookie, (void**)&descriptor) ) { MSG_ERR(("_ump_ukk_map_mem: cookie 0x%X not found for this session\n", args->cookie )); diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c b/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c index d6b59b7..cc7b8be 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c +++ b/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c @@ -1,9 +1,9 @@ /* * Copyright (C) 2010-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. */ @@ -65,9 +65,9 @@ void ump_descriptor_mapping_destroy(ump_descriptor_mapping * map) int ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping * map, void * target) { - int descriptor = -1;/*-EFAULT;*/ - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); - descriptor = _mali_osk_find_first_zero_bit(map->table->usage, map->current_nr_mappings); + int descriptor = -1;/*-EFAULT;*/ + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); + descriptor = _mali_osk_find_first_zero_bit(map->table->usage, map->current_nr_mappings); if (descriptor == map->current_nr_mappings) { int nr_mappings_new; @@ -89,8 +89,8 @@ int ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping * map, void * goto unlock_and_exit; } - _mali_osk_memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG); - _mali_osk_memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void*)); + _mali_osk_memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG); + _mali_osk_memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void*)); map->table = new_table; map->current_nr_mappings = nr_mappings_new; descriptor_table_free(old_table); @@ -107,10 +107,10 @@ unlock_and_exit: int ump_descriptor_mapping_get(ump_descriptor_mapping * map, int descriptor, void** target) { - int result = -1;/*-EFAULT;*/ - DEBUG_ASSERT(map); - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); - if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + int result = -1;/*-EFAULT;*/ + DEBUG_ASSERT(map); + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) { *target = map->table->mappings[descriptor]; result = 0; @@ -122,9 +122,9 @@ int ump_descriptor_mapping_get(ump_descriptor_mapping * map, int descriptor, voi int ump_descriptor_mapping_set(ump_descriptor_mapping * map, int descriptor, void * target) { - int result = -1;/*-EFAULT;*/ - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); - if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + int result = -1;/*-EFAULT;*/ + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) { map->table->mappings[descriptor] = target; result = 0; @@ -135,8 +135,8 @@ int ump_descriptor_mapping_set(ump_descriptor_mapping * map, int descriptor, voi void ump_descriptor_mapping_free(ump_descriptor_mapping * map, int descriptor) { - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); - if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) { map->table->mappings[descriptor] = NULL; _mali_osk_clear_nonatomic_bit(descriptor, map->table->usage); @@ -163,4 +163,3 @@ static void descriptor_table_free(ump_descriptor_table * table) { _mali_osk_free(table); } - diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h b/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h index a91ae28..73915ee 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h +++ b/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h @@ -1,9 +1,9 @@ /* * Copyright (C) 2010-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. */ @@ -40,6 +40,8 @@ typedef struct ump_memory_backend u32 (*stat)(struct ump_memory_backend *backend); int (*pre_allocate_physical_check)(void *ctx, u32 size); u32 (*adjust_to_mali_phys)(void *ctx, u32 cpu_phys); + void *(*get)(ump_dd_mem *mem, void *args); + void (*set)(ump_dd_mem *mem, void *args); void * ctx; } ump_memory_backend; @@ -47,4 +49,3 @@ ump_memory_backend * ump_memory_backend_create ( void ); void ump_memory_backend_destroy( void ); #endif /*__UMP_KERNEL_MEMORY_BACKEND_H__ */ - diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c b/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c index cd5825e..cb13232 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c +++ b/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c @@ -195,3 +195,66 @@ _mali_osk_errcode_t _ump_ukk_allocate( _ump_uk_allocate_s *user_interaction ) return _MALI_OSK_ERR_OK; } + + +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_meminfo_set(ump_dd_handle memh, void* args) +{ + ump_dd_mem * mem; + ump_secure_id secure_id; + + DEBUG_ASSERT_POINTER(memh); + + secure_id = ump_dd_secure_id_get(memh); + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) + { + device.backend->set(mem, args); + } + else + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Failed to look up mapping in ump_meminfo_set(). ID: %u\n", (ump_secure_id)secure_id)); + return UMP_DD_INVALID; + } + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + return UMP_DD_SUCCESS; +} + +UMP_KERNEL_API_EXPORT void *ump_dd_meminfo_get(ump_secure_id secure_id, void* args) +{ + ump_dd_mem * mem; + void *result; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) + { + result = device.backend->get(mem, args); + } + else + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Failed to look up mapping in ump_meminfo_get(). ID: %u\n", (ump_secure_id)secure_id)); + return UMP_DD_HANDLE_INVALID; + } + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + return result; +} + +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get_from_vaddr(unsigned long vaddr) +{ + ump_dd_mem * mem; + + DBG_MSG(5, ("Getting handle from Virtual address. vaddr: %u\n", vaddr)); + + _ump_osk_mem_mapregion_get(&mem, vaddr); + + DBG_MSG(1, ("Getting handle's Handle : 0x%8lx\n", mem)); + + return (ump_dd_handle)mem; +} + diff --git a/drivers/media/video/samsung/ump/common/ump_osk.h b/drivers/media/video/samsung/ump/common/ump_osk.h index cae0433..dabdc7f 100644 --- a/drivers/media/video/samsung/ump/common/ump_osk.h +++ b/drivers/media/video/samsung/ump/common/ump_osk.h @@ -1,9 +1,9 @@ /* * Copyright (C) 2010-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. */ @@ -42,6 +42,8 @@ void _ump_osk_mem_mapregion_term( ump_memory_allocation * descriptor ); void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk_msync_op op, ump_session_data * session_data ); +void _ump_osk_mem_mapregion_get( ump_dd_mem ** mem, unsigned long vaddr); + #ifdef __cplusplus } #endif diff --git a/drivers/media/video/samsung/ump/common/ump_uk_types.h b/drivers/media/video/samsung/ump/common/ump_uk_types.h index 4fd1ef7..143588d 100644 --- a/drivers/media/video/samsung/ump/common/ump_uk_types.h +++ b/drivers/media/video/samsung/ump/common/ump_uk_types.h @@ -49,7 +49,9 @@ typedef enum _UMP_IOC_SWITCH_HW_USAGE, _UMP_IOC_LOCK, _UMP_IOC_UNLOCK, +#ifdef CONFIG_ION_EXYNOS _UMP_IOC_ION_IMPORT, +#endif }_ump_uk_functions; typedef enum @@ -108,6 +110,7 @@ typedef struct _ump_uk_allocate_s ump_uk_alloc_constraints constraints; /**< Only input to Devicedriver */ } _ump_uk_allocate_s; +#ifdef CONFIG_ION_EXYNOS typedef struct _ump_uk_ion_import_s { void *ctx; /**< [in,out] user-kernel context (trashed on output) */ @@ -116,6 +119,7 @@ typedef struct _ump_uk_ion_import_s u32 size; /**< Input and output. Requested size; input. Returned size; output */ ump_uk_alloc_constraints constraints; /**< Only input to Devicedriver */ } _ump_uk_ion_import_s; +#endif /** * SIZE_GET ([in] u32 secure_id, [out]size ) diff --git a/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h b/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h index c993746..36c5c9d 100644 --- a/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h +++ b/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h @@ -1,9 +1,9 @@ /* * Copyright (C) 2010, 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. */ @@ -23,6 +23,10 @@ extern "C" { /** Turn specified physical memory into UMP memory. */ UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block * blocks, unsigned long num_blocks); +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get(ump_secure_id secure_id); +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_meminfo_set(ump_dd_handle memh, void* args); +UMP_KERNEL_API_EXPORT void *ump_dd_meminfo_get(ump_secure_id secure_id, void* args); +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get_from_vaddr(unsigned long vaddr); #ifdef __cplusplus } diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c b/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c index 158cc88..a358a3c 100644 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c @@ -92,7 +92,7 @@ static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int c #endif static int ump_file_mmap(struct file * filp, struct vm_area_struct * vma); -#if defined(CONFIG_VIDEO_MALI400MP) +#if defined(CONFIG_VIDEO_UMP) extern int map_errcode( _mali_osk_errcode_t err ); #endif @@ -400,7 +400,7 @@ static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int c return err; } -#ifndef CONFIG_VIDEO_MALI400MP +#ifndef CONFIG_VIDEO_UMP int map_errcode( _mali_osk_errcode_t err ) { switch(err) @@ -429,7 +429,7 @@ static int ump_file_mmap(struct file * filp, struct vm_area_struct * vma) /* Validate the session data */ session_data = (struct ump_session_data *)filp->private_data; - if (NULL == session_data) + if (NULL == session_data || NULL == session_data->cookies_map->table->mappings) { MSG_ERR(("mmap() called without any session data available\n")); return -EFAULT; @@ -474,6 +474,9 @@ EXPORT_SYMBOL(ump_dd_phys_blocks_get); EXPORT_SYMBOL(ump_dd_size_get); EXPORT_SYMBOL(ump_dd_reference_add); EXPORT_SYMBOL(ump_dd_reference_release); +EXPORT_SYMBOL(ump_dd_meminfo_get); +EXPORT_SYMBOL(ump_dd_meminfo_set); +EXPORT_SYMBOL(ump_dd_handle_get_from_vaddr); /* Export our own extended kernel space allocator */ EXPORT_SYMBOL(ump_dd_handle_create_from_phys_blocks); diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c index 463e609..82c16cc 100644 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c @@ -1,9 +1,9 @@ /* * Copyright (C) 2010-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. */ @@ -108,6 +108,8 @@ ump_memory_backend * ump_block_allocator_create(u32 base_address, u32 size) backend->stat = block_allocator_stat; backend->pre_allocate_physical_check = NULL; backend->adjust_to_mali_phys = NULL; + backend->get = NULL; + backend->set = NULL; return backend; } diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c index fc3afa8..8f6a9b3 100644 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c @@ -77,6 +77,8 @@ ump_memory_backend * ump_os_memory_backend_create(const int max_allocation) backend->stat = os_stat; backend->pre_allocate_physical_check = NULL; backend->adjust_to_mali_phys = NULL; + backend->get = NULL; + backend->set = NULL; return backend; } @@ -134,19 +136,20 @@ static int os_allocate(void* ctx, ump_dd_mem * descriptor) return 0; /* failure */ } - while (left > 0 && ((info->num_pages_allocated + pages_allocated) < info->num_pages_max)) + while (left > 0) { struct page * new_page; if (is_cached) { - new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN); + new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN ); } else { - new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN | __GFP_COLD); + new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN | __GFP_COLD); } if (NULL == new_page) { + MSG_ERR(("UMP memory allocated: Out of Memory !!\n")); break; } @@ -180,6 +183,8 @@ static int os_allocate(void* ctx, ump_dd_mem * descriptor) if (left) { DBG_MSG(1, ("Failed to allocate needed pages\n")); + DBG_MSG(1, ("UMP memory allocated: %d kB Configured maximum OS memory usage: %d kB\n", + (pages_allocated * _MALI_OSK_CPU_PAGE_SIZE)/1024, (info->num_pages_max* _MALI_OSK_CPU_PAGE_SIZE)/1024)); while(pages_allocated) { diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c new file mode 100644 index 0000000..46797ea --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2010-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. + */ + +/* create by boojin.kim@samsung.com */ +/* needed to detect kernel version specific code */ +#include <linux/version.h> + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#include <linux/semaphore.h> +#else /* pre 2.6.26 the file was in the arch specific location */ +#include <asm/semaphore.h> +#endif + +#include <linux/mm.h> +#include <linux/slab.h> +#include <asm/atomic.h> +#include <linux/vmalloc.h> +#include <asm/cacheflush.h> +#include "ump_kernel_common.h" +#include "ump_kernel_memory_backend.h" +#include "ump_kernel_interface_ref_drv.h" +#include "ump_kernel_memory_backend_vcm.h" +#include "../common/ump_uk_types.h" +#include <linux/vcm-drv.h> +#include <plat/s5p-vcm.h> +#include <linux/dma-mapping.h> + +#define UMP_REF_DRV_UK_VCM_DEV_G2D 12 + +typedef struct ump_vcm { + struct vcm *vcm; + struct vcm_res *vcm_res; + unsigned int dev_id; +} ump_vcm; + +typedef struct vcm_allocator { + struct semaphore mutex; + u32 num_vcm_blocks; +} vcm_allocator; + +static void ump_vcm_free(void* ctx, ump_dd_mem * descriptor); +static int ump_vcm_allocate(void* ctx, ump_dd_mem * descriptor); +static void *vcm_res_get(ump_dd_mem *mem, void* args); +static void vcm_attr_set(ump_dd_mem *mem, void* args); +static int vcm_mem_allocator(vcm_allocator *info, ump_dd_mem *descriptor); +static void vcm_memory_backend_destroy(ump_memory_backend * backend); + + +/* + * Create VCM memory backend + */ +ump_memory_backend * ump_vcm_memory_backend_create(const int max_allocation) +{ + ump_memory_backend * backend; + vcm_allocator * info; + + info = kmalloc(sizeof(vcm_allocator), GFP_KERNEL); + if (NULL == info) + { + return NULL; + } + + info->num_vcm_blocks = 0; + + + sema_init(&info->mutex, 1); + + backend = kmalloc(sizeof(ump_memory_backend), GFP_KERNEL); + if (NULL == backend) + { + kfree(info); + return NULL; + } + + backend->ctx = info; + backend->allocate = ump_vcm_allocate; + backend->release = ump_vcm_free; + backend->shutdown = vcm_memory_backend_destroy; + backend->pre_allocate_physical_check = NULL; + backend->adjust_to_mali_phys = NULL; + + backend->get = vcm_res_get; + backend->set = vcm_attr_set; + + + return backend; +} + +/* + * Destroy specified VCM memory backend + */ +static void vcm_memory_backend_destroy(ump_memory_backend * backend) +{ + vcm_allocator * info = (vcm_allocator*)backend->ctx; +#if 0 + DBG_MSG_IF(1, 0 != info->num_pages_allocated, ("%d pages still in use during shutdown\n", info->num_pages_allocated)); +#endif + kfree(info); + kfree(backend); +} + +/* + * Allocate UMP memory + */ +static int ump_vcm_allocate(void *ctx, ump_dd_mem * descriptor) +{ + int ret; /* success */ + vcm_allocator *info; + struct ump_vcm *ump_vcm; + + BUG_ON(!descriptor); + BUG_ON(!ctx); + + info = (vcm_allocator*)ctx; + + ump_vcm = kmalloc(sizeof(struct ump_vcm), GFP_KERNEL); + if (NULL == ump_vcm) + { + return 0; + } + + ump_vcm->dev_id = (int)descriptor->backend_info & ~UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE; + + if(ump_vcm->dev_id == UMP_REF_DRV_UK_CONSTRAINT_NONE) { /* None */ + ump_vcm->dev_id = UMP_REF_DRV_UK_VCM_DEV_G2D; /* this ID is G2D */ + } + else if(ump_vcm->dev_id == UMP_REF_DRV_UK_CONSTRAINT_PHYSICALLY_LINEAR) { /* Physical Linear */ + return 0; + } + else { /* Other VCM */ + ump_vcm->dev_id -= 2; + } + + DBG_MSG(5, ("Device ID for VCM : %d\n", ump_vcm->dev_id)); + ump_vcm->vcm = vcm_find_vcm(ump_vcm->dev_id); + + if (!ump_vcm->vcm) + { + return 0; + } + descriptor->backend_info = (void*)ump_vcm; + + if (down_interruptible(&info->mutex)) { + DBG_MSG(1, ("Failed to get mutex in ump_vcm_allocate\n")); + return 0; /* failure */ + } + + ret = vcm_mem_allocator(info, descriptor); + up(&info->mutex); + + return ret; /* success */ +} + +static int vcm_mem_allocator(vcm_allocator *info, ump_dd_mem *descriptor) +{ + unsigned long num_blocks; + int i; + struct vcm_phys *phys; + struct vcm_phys_part *part; + int size_total = 0; + struct ump_vcm *ump_vcm; + + ump_vcm = (struct ump_vcm*)descriptor->backend_info; + + ump_vcm->vcm_res = + vcm_make_binding(ump_vcm->vcm, descriptor->size_bytes, + ump_vcm->dev_id, 0); + + phys = ump_vcm->vcm_res->phys; + part = phys->parts; + num_blocks = phys->count; + + DBG_MSG(5, + ("Allocating page array. Size: %lu, VCM Reservation : 0x%x\n", + phys->count * sizeof(ump_dd_physical_block), + ump_vcm->vcm_res->start)); + + /* Now, make a copy of the block information supplied by the user */ + descriptor->block_array = + (ump_dd_physical_block *) vmalloc(sizeof(ump_dd_physical_block) * + num_blocks); + + if (NULL == descriptor->block_array) { + vfree(descriptor->block_array); + DBG_MSG(1, ("Could not allocate a mem handle for function.\n")); + return 0; /* failure */ + } + + for (i = 0; i < num_blocks; i++) { + descriptor->block_array[i].addr = part->start; + descriptor->block_array[i].size = part->size; + + dmac_unmap_area(phys_to_virt(part->start), part->size, DMA_FROM_DEVICE); + outer_inv_range(part->start, part->start + part->size); + + ++part; + size_total += descriptor->block_array[i].size; + DBG_MSG(6, + ("UMP memory created with VCM. addr 0x%x, size: 0x%x\n", + descriptor->block_array[i].addr, + descriptor->block_array[i].size)); + } + + descriptor->size_bytes = size_total; + descriptor->nr_blocks = num_blocks; + descriptor->ctx = NULL; + + info->num_vcm_blocks += num_blocks; + return 1; +} + +/* + * Free specified UMP memory + */ +static void ump_vcm_free(void *ctx, ump_dd_mem * descriptor) +{ + struct ump_vcm *ump_vcm; + vcm_allocator *info; + + BUG_ON(!descriptor); + BUG_ON(!ctx); + + ump_vcm = (struct ump_vcm*)descriptor->backend_info; + info = (vcm_allocator*)ctx; + + BUG_ON(descriptor->nr_blocks > info->num_vcm_blocks); + + if (down_interruptible(&info->mutex)) { + DBG_MSG(1, ("Failed to get mutex in ump_vcm_free\n")); + return; + } + + DBG_MSG(5, ("Releasing %lu VCM pages\n", descriptor->nr_blocks)); + + info->num_vcm_blocks -= descriptor->nr_blocks; + + up(&info->mutex); + + DBG_MSG(6, ("Freeing physical page by VCM\n")); + vcm_destroy_binding(ump_vcm->vcm_res); + ump_vcm->vcm = NULL; + ump_vcm->vcm_res = NULL; + + kfree(ump_vcm); + vfree(descriptor->block_array); +} + +static void *vcm_res_get(ump_dd_mem *mem, void *args) +{ + struct ump_vcm *ump_vcm; + enum vcm_dev_id vcm_id; + + ump_vcm = (struct ump_vcm*)mem->backend_info; + vcm_id = (enum vcm_dev_id)args; + + if (vcm_reservation_in_vcm + (vcm_find_vcm(vcm_id), ump_vcm->vcm_res) + == S5PVCM_RES_NOT_IN_VCM) + return NULL; + else + return ump_vcm->vcm_res; +} + +static void vcm_attr_set(ump_dd_mem *mem, void *args) +{ + struct ump_vcm *ump_vcm, *ump_vcmh; + + ump_vcm = (struct ump_vcm*)args; + + ump_vcmh = kmalloc(sizeof(struct ump_vcm), GFP_KERNEL); + if (NULL == ump_vcmh) + { + return; + } + + ump_vcmh->dev_id = ump_vcm->dev_id; + ump_vcmh->vcm = ump_vcm->vcm; + ump_vcmh->vcm_res = ump_vcm->vcm_res; + + mem->backend_info= (void*)ump_vcmh; + + return; +} diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h new file mode 100644 index 0000000..c1ead0d --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2010-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. + */ + +/** + * @file ump_kernel_memory_backend_vcm.h + */ + +#ifndef __UMP_KERNEL_MEMORY_BACKEND_VCM_H__ +#define __UMP_KERNEL_MEMORY_BACKEND_VCM_H__ + +#include "ump_kernel_memory_backend.h" + +ump_memory_backend * ump_vcm_memory_backend_create(const int max_allocation); + +#endif /* __UMP_KERNEL_MEMORY_BACKEND_VCM_H__ */ diff --git a/drivers/media/video/samsung/ump/linux/ump_memory_backend.c b/drivers/media/video/samsung/ump/linux/ump_memory_backend.c index 23357f4..d067cfe 100644 --- a/drivers/media/video/samsung/ump/linux/ump_memory_backend.c +++ b/drivers/media/video/samsung/ump/linux/ump_memory_backend.c @@ -56,6 +56,13 @@ ump_memory_backend* ump_memory_backend_create ( void ) DBG_MSG(2, ("Using OS memory backend, allocation limit: %d\n", ump_memory_size)); backend = ump_os_memory_backend_create(ump_memory_size); } +#ifdef CONFIG_UMP_VCM_ALLOC + else if (2 == ump_backend) + { + DBG_MSG(2, ("Using VCM memory backend, allocation limit: %d\n", ump_memory_size)); + backend = ump_vcm_memory_backend_create(ump_memory_size); + } +#endif return backend; } diff --git a/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c b/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c index 0073c4d..8ae169a 100644 --- a/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c +++ b/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c @@ -23,6 +23,7 @@ #include <linux/module.h> /* kernel module definitions */ #include <linux/kernel.h> #include <linux/mm.h> +#include <linux/sched.h> #include <linux/slab.h> #include <asm/memory.h> @@ -210,6 +211,95 @@ _mali_osk_errcode_t _ump_osk_mem_mapregion_map( ump_memory_allocation * descript return retval; } +static u32 _ump_osk_virt_to_phys_start(ump_dd_mem * mem, u32 start, u32 address, int *index) +{ + int i; + u32 offset = address - start; + ump_dd_physical_block *block; + u32 sum = 0; + + for (i=0; i<mem->nr_blocks; i++) { + block = &mem->block_array[i]; + sum += block->size; + if (sum > offset) { + *index = i; + DBG_MSG(3, ("_ump_osk_virt_to_phys : index : %d, virtual 0x%x, phys 0x%x\n", i, address, (u32)block->addr + offset - (sum -block->size))); + return (u32)block->addr + offset - (sum -block->size); + } + } + + return _MALI_OSK_ERR_FAULT; +} + +static u32 _ump_osk_virt_to_phys_end(ump_dd_mem * mem, u32 start, u32 address, int *index) +{ + int i; + u32 offset = address - start; + ump_dd_physical_block *block; + u32 sum = 0; + + for (i=0; i<mem->nr_blocks; i++) { + block = &mem->block_array[i]; + sum += block->size; + if (sum >= offset) { + *index = i; + DBG_MSG(3, ("_ump_osk_virt_to_phys : index : %d, virtual 0x%x, phys 0x%x\n", i, address, (u32)block->addr + offset - (sum -block->size))); + return (u32)block->addr + offset - (sum -block->size); + } + } + + return _MALI_OSK_ERR_FAULT; +} + +static void _ump_osk_msync_with_virt(ump_dd_mem * mem, ump_uk_msync_op op, u32 start, u32 address, u32 size) +{ + int start_index, end_index; + u32 start_p, end_p; + + DBG_MSG(3, ("Cache flush with user virtual address. start : 0x%x, end : 0x%x, address 0x%x, size 0x%x\n", start, start+mem->size_bytes, address, size)); + + start_p = _ump_osk_virt_to_phys_start(mem, start, address, &start_index); + end_p = _ump_osk_virt_to_phys_end(mem, start, address+size, &end_index); + + if (start_index==end_index) { + if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) + outer_flush_range(start_p, end_p); + else + outer_clean_range(start_p, end_p); + } else { + ump_dd_physical_block *block; + int i; + + for (i=start_index; i<=end_index; i++) { + block = &mem->block_array[i]; + + if (i == start_index) { + if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) { + outer_flush_range(start_p, block->addr+block->size); + } else { + outer_clean_range(start_p, block->addr+block->size); + } + } + else if (i == end_index) { + if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) { + outer_flush_range(block->addr, end_p); + } else { + outer_clean_range(block->addr, end_p); + } + break; + } + else { + if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) { + outer_flush_range(block->addr, block->addr+block->size); + } else { + outer_clean_range(block->addr, block->addr+block->size); + } + } + } + } + return; +} + static void level1_cache_flush_all(void) { DBG_MSG(4, ("UMP[xx] Flushing complete L1 cache\n")); @@ -229,7 +319,11 @@ void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk end_v = (void *)(start_v + size - 1); /* There is no dmac_clean_range, so the L1 is always flushed, * also for UMP_MSYNC_CLEAN. */ - dmac_flush_range(start_v, end_v); + if (size >= SZ_64K) + flush_all_cpu_caches(); + else + dmac_flush_range(start_v, end_v); + DBG_MSG(3, ("UMP[%02u] Flushing CPU L1 Cache. Cpu address: %x-%x\n", mem->secure_id, start_v,end_v)); } else @@ -278,6 +372,14 @@ void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk /* Flush L2 using physical addresses, block for block. */ + if ((virt!=NULL) && (mem->size_bytes >= SZ_1M)) { + if (op == _UMP_UK_MSYNC_CLEAN) + outer_clean_all(); + else if ((op == _UMP_UK_MSYNC_INVALIDATE) || (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE)) + outer_flush_all(); + return; + } + for (i=0 ; i < mem->nr_blocks; i++) { u32 start_p, end_p; @@ -344,3 +446,40 @@ void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk return; } + +void _ump_osk_mem_mapregion_get( ump_dd_mem ** mem, unsigned long vaddr) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + ump_vma_usage_tracker * vma_usage_tracker; + ump_memory_allocation *descriptor; + ump_dd_handle handle; + + DBG_MSG(3, ("_ump_osk_mem_mapregion_get: vaddr 0x%08lx\n", vaddr)); + + down_read(&mm->mmap_sem); + vma = find_vma(mm, vaddr); + up_read(&mm->mmap_sem); + if(!vma) + { + DBG_MSG(3, ("Not found VMA\n")); + *mem = NULL; + return; + } + DBG_MSG(4, ("Get vma: 0x%08lx vma->vm_start: 0x%08lx\n", (unsigned long)vma, vma->vm_start)); + + vma_usage_tracker = (struct ump_vma_usage_tracker*)vma->vm_private_data; + if(vma_usage_tracker == NULL) + { + DBG_MSG(3, ("Not found vma_usage_tracker\n")); + *mem = NULL; + return; + } + + descriptor = (struct ump_memory_allocation*)vma_usage_tracker->descriptor; + handle = (ump_dd_handle)descriptor->handle; + + DBG_MSG(3, ("Get handle: 0x%08lx\n", handle)); + *mem = (ump_dd_mem*)handle; +} + diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c b/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c index 9692e5b..a6691ed 100644 --- a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c +++ b/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c @@ -89,7 +89,6 @@ int ump_allocate_wrapper(u32 __user * argument, struct ump_session_data * sessi return 0; /* success */ } - #ifdef CONFIG_ION_EXYNOS /* * IOCTL operation; Import fd to UMP memory @@ -130,6 +129,12 @@ int ump_ion_import_wrapper(u32 __user * argument, struct ump_session_data * ses sg_ion = ion_map_dma(ion_client_ump,ion_hnd); blocks = (ump_dd_physical_block*)_mali_osk_malloc(sizeof(ump_dd_physical_block)*1024); + + if (NULL == blocks) { + MSG_ERR(("Failed to allocate blocks in ump_ioctl_allocate()\n")); + return -ENOMEM; + } + sg = sg_ion; do { blocks[i].addr = sg_phys(sg); |