xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/mali400/mali/linux/mali_osk_low_level_mem.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (C) 2010-2014, 2016-2017 ARM Limited. All rights reserved.
3  *
4  * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5  * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
6  *
7  * A copy of the licence is included with the program, and can also be obtained from Free Software
8  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
9  */
10 
11 /**
12  * @file mali_osk_low_level_mem.c
13  * Implementation of the OS abstraction layer for the kernel device driver
14  */
15 
16 #include <asm/io.h>
17 #include <linux/ioport.h>
18 #include <linux/slab.h>
19 
20 #include "mali_kernel_common.h"
21 #include "mali_osk.h"
22 #include "mali_ukk.h"
23 
_mali_osk_mem_barrier(void)24 void _mali_osk_mem_barrier(void)
25 {
26 	mb();
27 }
28 
_mali_osk_write_mem_barrier(void)29 void _mali_osk_write_mem_barrier(void)
30 {
31 	wmb();
32 }
33 
_mali_osk_mem_mapioregion(uintptr_t phys,u32 size,const char * description)34 mali_io_address _mali_osk_mem_mapioregion(uintptr_t phys, u32 size, const char *description)
35 {
36 	return (mali_io_address)ioremap(phys, size);
37 }
38 
_mali_osk_mem_unmapioregion(uintptr_t phys,u32 size,mali_io_address virt)39 void _mali_osk_mem_unmapioregion(uintptr_t phys, u32 size, mali_io_address virt)
40 {
41 	iounmap((void *)virt);
42 }
43 
_mali_osk_mem_reqregion(uintptr_t phys,u32 size,const char * description)44 _mali_osk_errcode_t inline _mali_osk_mem_reqregion(uintptr_t phys, u32 size, const char *description)
45 {
46 #if MALI_LICENSE_IS_GPL
47 	return _MALI_OSK_ERR_OK; /* GPL driver gets the mem region for the resources registered automatically */
48 #else
49 	return ((NULL == request_mem_region(phys, size, description)) ? _MALI_OSK_ERR_NOMEM : _MALI_OSK_ERR_OK);
50 #endif
51 }
52 
_mali_osk_mem_unreqregion(uintptr_t phys,u32 size)53 void inline _mali_osk_mem_unreqregion(uintptr_t phys, u32 size)
54 {
55 #if !MALI_LICENSE_IS_GPL
56 	release_mem_region(phys, size);
57 #endif
58 }
59 
_mali_osk_mem_iowrite32_relaxed(volatile mali_io_address addr,u32 offset,u32 val)60 void inline _mali_osk_mem_iowrite32_relaxed(volatile mali_io_address addr, u32 offset, u32 val)
61 {
62 	__raw_writel(cpu_to_le32(val), ((u8 *)addr) + offset);
63 }
64 
_mali_osk_mem_ioread32(volatile mali_io_address addr,u32 offset)65 u32 inline _mali_osk_mem_ioread32(volatile mali_io_address addr, u32 offset)
66 {
67 	return ioread32(((u8 *)addr) + offset);
68 }
69 
_mali_osk_mem_iowrite32(volatile mali_io_address addr,u32 offset,u32 val)70 void inline _mali_osk_mem_iowrite32(volatile mali_io_address addr, u32 offset, u32 val)
71 {
72 	iowrite32(val, ((u8 *)addr) + offset);
73 }
74 
_mali_osk_cache_flushall(void)75 void _mali_osk_cache_flushall(void)
76 {
77 	/** @note Cached memory is not currently supported in this implementation */
78 }
79 
_mali_osk_cache_ensure_uncached_range_flushed(void * uncached_mapping,u32 offset,u32 size)80 void _mali_osk_cache_ensure_uncached_range_flushed(void *uncached_mapping, u32 offset, u32 size)
81 {
82 	_mali_osk_write_mem_barrier();
83 }
84 
_mali_osk_mem_write_safe(void __user * dest,const void __user * src,u32 size)85 u32 _mali_osk_mem_write_safe(void __user *dest, const void __user *src, u32 size)
86 {
87 #define MALI_MEM_SAFE_COPY_BLOCK_SIZE 4096
88 	u32 retval = 0;
89 	void *temp_buf;
90 
91 	temp_buf = kmalloc(MALI_MEM_SAFE_COPY_BLOCK_SIZE, GFP_KERNEL);
92 	if (NULL != temp_buf) {
93 		u32 bytes_left_to_copy = size;
94 		u32 i;
95 		for (i = 0; i < size; i += MALI_MEM_SAFE_COPY_BLOCK_SIZE) {
96 			u32 size_to_copy;
97 			u32 size_copied;
98 			u32 bytes_left;
99 
100 			if (bytes_left_to_copy > MALI_MEM_SAFE_COPY_BLOCK_SIZE) {
101 				size_to_copy = MALI_MEM_SAFE_COPY_BLOCK_SIZE;
102 			} else {
103 				size_to_copy = bytes_left_to_copy;
104 			}
105 
106 			bytes_left = copy_from_user(temp_buf, ((char *)src) + i, size_to_copy);
107 			size_copied = size_to_copy - bytes_left;
108 
109 			bytes_left = copy_to_user(((char *)dest) + i, temp_buf, size_copied);
110 			size_copied -= bytes_left;
111 
112 			bytes_left_to_copy -= size_copied;
113 			retval += size_copied;
114 
115 			if (size_copied != size_to_copy) {
116 				break; /* Early out, we was not able to copy this entire block */
117 			}
118 		}
119 
120 		kfree(temp_buf);
121 	}
122 
123 	return retval;
124 }
125 
_mali_ukk_mem_write_safe(_mali_uk_mem_write_safe_s * args)126 _mali_osk_errcode_t _mali_ukk_mem_write_safe(_mali_uk_mem_write_safe_s *args)
127 {
128 	void __user *src;
129 	void __user *dst;
130 	struct mali_session_data *session;
131 
132 	MALI_DEBUG_ASSERT_POINTER(args);
133 
134 	session = (struct mali_session_data *)(uintptr_t)args->ctx;
135 
136 	if (NULL == session) {
137 		return _MALI_OSK_ERR_INVALID_ARGS;
138 	}
139 
140 	src = (void __user *)(uintptr_t)args->src;
141 	dst = (void __user *)(uintptr_t)args->dest;
142 
143 	/* Return number of bytes actually copied */
144 	args->size = _mali_osk_mem_write_safe(dst, src, args->size);
145 	return _MALI_OSK_ERR_OK;
146 }
147