import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / gpu / mt8127 / mali / mali / linux / mali_ukk_mem.c
CommitLineData
6fa3eb70
S
1/*
2 * This confidential and proprietary software may be used only as
3 * authorised by a licensing agreement from ARM Limited
4 * (C) COPYRIGHT 2008-2013 ARM Limited
5 * ALL RIGHTS RESERVED
6 * The entire notice above must be reproduced on all authorised
7 * copies and copies may only be made to the extent permitted
8 * by a licensing agreement from ARM Limited.
9 */
10#include <linux/fs.h> /* file system operations */
11#include <asm/uaccess.h> /* user space access */
12
13#include "mali_ukk.h"
14#include "mali_osk.h"
15#include "mali_kernel_common.h"
16#include "mali_session.h"
17#include "mali_ukk_wrappers.h"
18
19int mem_write_safe_wrapper(struct mali_session_data *session_data, _mali_uk_mem_write_safe_s __user * uargs)
20{
21 _mali_uk_mem_write_safe_s kargs;
22 _mali_osk_errcode_t err;
23
24 MALI_CHECK_NON_NULL(uargs, -EINVAL);
25 MALI_CHECK_NON_NULL(session_data, -EINVAL);
26
27 if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_mem_write_safe_s))) {
28 return -EFAULT;
29 }
30
31 kargs.ctx = session_data;
32
33 /* Check if we can access the buffers */
34 if (!access_ok(VERIFY_WRITE, kargs.dest, kargs.size)
35 || !access_ok(VERIFY_READ, kargs.src, kargs.size)) {
36 return -EINVAL;
37 }
38
39 /* Check if size wraps */
40 if ((kargs.size + kargs.dest) <= kargs.dest
41 || (kargs.size + kargs.src) <= kargs.src) {
42 return -EINVAL;
43 }
44
45 err = _mali_ukk_mem_write_safe(&kargs);
46 if (_MALI_OSK_ERR_OK != err) {
47 return map_errcode(err);
48 }
49
50 if (0 != put_user(kargs.size, &uargs->size)) {
51 return -EFAULT;
52 }
53
54 return 0;
55}
56
57int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user * argument)
58{
59 _mali_uk_map_external_mem_s uk_args;
60 _mali_osk_errcode_t err_code;
61
62 /* validate input */
63 /* the session_data pointer was validated by caller */
64 MALI_CHECK_NON_NULL( argument, -EINVAL);
65
66 /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
67 if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_map_external_mem_s)) ) {
68 return -EFAULT;
69 }
70
71 uk_args.ctx = session_data;
72 err_code = _mali_ukk_map_external_mem( &uk_args );
73
74 if (0 != put_user(uk_args.cookie, &argument->cookie)) {
75 if (_MALI_OSK_ERR_OK == err_code) {
76 /* Rollback */
77 _mali_uk_unmap_external_mem_s uk_args_unmap;
78
79 uk_args_unmap.ctx = session_data;
80 uk_args_unmap.cookie = uk_args.cookie;
81 err_code = _mali_ukk_unmap_external_mem( &uk_args_unmap );
82 if (_MALI_OSK_ERR_OK != err_code) {
83 MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_unmap_external_mem, as a result of failing put_user(), failed\n"));
84 }
85 }
86 return -EFAULT;
87 }
88
89 /* Return the error that _mali_ukk_free_big_block produced */
90 return map_errcode(err_code);
91}
92
93int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap_external_mem_s __user * argument)
94{
95 _mali_uk_unmap_external_mem_s uk_args;
96 _mali_osk_errcode_t err_code;
97
98 /* validate input */
99 /* the session_data pointer was validated by caller */
100 MALI_CHECK_NON_NULL( argument, -EINVAL);
101
102 /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
103 if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_unmap_external_mem_s)) ) {
104 return -EFAULT;
105 }
106
107 uk_args.ctx = session_data;
108 err_code = _mali_ukk_unmap_external_mem( &uk_args );
109
110 /* Return the error that _mali_ukk_free_big_block produced */
111 return map_errcode(err_code);
112}
113
114#if defined(CONFIG_MALI400_UMP)
115int mem_release_ump_wrapper(struct mali_session_data *session_data, _mali_uk_release_ump_mem_s __user * argument)
116{
117 _mali_uk_release_ump_mem_s uk_args;
118 _mali_osk_errcode_t err_code;
119
120 /* validate input */
121 /* the session_data pointer was validated by caller */
122 MALI_CHECK_NON_NULL( argument, -EINVAL);
123
124 /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
125 if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_release_ump_mem_s)) ) {
126 return -EFAULT;
127 }
128
129 uk_args.ctx = session_data;
130 err_code = _mali_ukk_release_ump_mem( &uk_args );
131
132 /* Return the error that _mali_ukk_free_big_block produced */
133 return map_errcode(err_code);
134}
135
136int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_attach_ump_mem_s __user * argument)
137{
138 _mali_uk_attach_ump_mem_s uk_args;
139 _mali_osk_errcode_t err_code;
140
141 /* validate input */
142 /* the session_data pointer was validated by caller */
143 MALI_CHECK_NON_NULL( argument, -EINVAL);
144
145 /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
146 if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_attach_ump_mem_s)) ) {
147 return -EFAULT;
148 }
149
150 uk_args.ctx = session_data;
151 err_code = _mali_ukk_attach_ump_mem( &uk_args );
152
153 if (0 != put_user(uk_args.cookie, &argument->cookie)) {
154 if (_MALI_OSK_ERR_OK == err_code) {
155 /* Rollback */
156 _mali_uk_release_ump_mem_s uk_args_unmap;
157
158 uk_args_unmap.ctx = session_data;
159 uk_args_unmap.cookie = uk_args.cookie;
160 err_code = _mali_ukk_release_ump_mem( &uk_args_unmap );
161 if (_MALI_OSK_ERR_OK != err_code) {
162 MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_attach_mem, as a result of failing put_user(), failed\n"));
163 }
164 }
165 return -EFAULT;
166 }
167
168 /* Return the error that _mali_ukk_map_external_ump_mem produced */
169 return map_errcode(err_code);
170}
171#endif /* CONFIG_MALI400_UMP */
172
173int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user * uargs)
174{
175 _mali_uk_query_mmu_page_table_dump_size_s kargs;
176 _mali_osk_errcode_t err;
177
178 MALI_CHECK_NON_NULL(uargs, -EINVAL);
179 MALI_CHECK_NON_NULL(session_data, -EINVAL);
180
181 kargs.ctx = session_data;
182
183 err = _mali_ukk_query_mmu_page_table_dump_size(&kargs);
184 if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
185
186 if (0 != put_user(kargs.size, &uargs->size)) return -EFAULT;
187
188 return 0;
189}
190
191int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user * uargs)
192{
193 _mali_uk_dump_mmu_page_table_s kargs;
194 _mali_osk_errcode_t err;
195 void *buffer;
196 int rc = -EFAULT;
197
198 /* validate input */
199 MALI_CHECK_NON_NULL(uargs, -EINVAL);
200 /* the session_data pointer was validated by caller */
201
202 kargs.buffer = NULL;
203
204 /* get location of user buffer */
205 if (0 != get_user(buffer, &uargs->buffer)) goto err_exit;
206 /* get size of mmu page table info buffer from user space */
207 if ( 0 != get_user(kargs.size, &uargs->size) ) goto err_exit;
208 /* verify we can access the whole of the user buffer */
209 if (!access_ok(VERIFY_WRITE, buffer, kargs.size)) goto err_exit;
210
211 /* allocate temporary buffer (kernel side) to store mmu page table info */
212 MALI_CHECK(kargs.size > 0, -ENOMEM);
213 kargs.buffer = _mali_osk_valloc(kargs.size);
214 if (NULL == kargs.buffer) {
215 rc = -ENOMEM;
216 goto err_exit;
217 }
218
219 kargs.ctx = session_data;
220 err = _mali_ukk_dump_mmu_page_table(&kargs);
221 if (_MALI_OSK_ERR_OK != err) {
222 rc = map_errcode(err);
223 goto err_exit;
224 }
225
226 /* copy mmu page table info back to user space and update pointers */
227 if (0 != copy_to_user(uargs->buffer, kargs.buffer, kargs.size) ) goto err_exit;
228 if (0 != put_user((kargs.register_writes - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->register_writes)) goto err_exit;
229 if (0 != put_user((kargs.page_table_dump - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->page_table_dump)) goto err_exit;
230 if (0 != put_user(kargs.register_writes_size, &uargs->register_writes_size)) goto err_exit;
231 if (0 != put_user(kargs.page_table_dump_size, &uargs->page_table_dump_size)) goto err_exit;
232 rc = 0;
233
234err_exit:
235 if (kargs.buffer) _mali_osk_vfree(kargs.buffer);
236 return rc;
237}