aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c')
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c141
1 files changed, 140 insertions, 1 deletions
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;
+}
+