tizen 2.4 release
[kernel/linux-3.0.git] / drivers / gpu / arm / mali400 / r4p0_rel0 / linux / mali_ukk_mem.c
1 /*
2  * Copyright (C) 2010-2012 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 #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
19 int 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
57 int 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
93 int 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)
115 int 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
136 int 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
173 int 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
191 int 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
234 err_exit:
235         if (kargs.buffer) _mali_osk_vfree(kargs.buffer);
236         return rc;
237 }