tizen 2.4 release
[kernel/linux-3.0.git] / drivers / gpu / arm / mali400 / mali / linux / mali_ukk_mem.c
1 /*
2  * Copyright (C) 2011-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_init_wrapper(struct mali_session_data *session_data, _mali_uk_init_mem_s __user *uargs)
20 {
21     _mali_uk_init_mem_s kargs;
22     _mali_osk_errcode_t err;
23
24     MALI_CHECK_NON_NULL(uargs, -EINVAL);
25
26     kargs.ctx = session_data;
27     err = _mali_ukk_init_mem(&kargs);
28     if (_MALI_OSK_ERR_OK != err)
29     {
30         return map_errcode(err);
31     }
32
33     if (0 != put_user(kargs.mali_address_base, &uargs->mali_address_base)) goto mem_init_rollback;
34     if (0 != put_user(kargs.memory_size, &uargs->memory_size)) goto mem_init_rollback;
35
36     return 0;
37
38 mem_init_rollback:
39         {
40                 _mali_uk_term_mem_s kargs;
41                 kargs.ctx = session_data;
42                 err = _mali_ukk_term_mem(&kargs);
43                 if (_MALI_OSK_ERR_OK != err)
44                 {
45                         MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_init_mem, as a result of failing put_user(), failed\n"));
46                 }
47         }
48     return -EFAULT;
49 }
50
51 int mem_term_wrapper(struct mali_session_data *session_data, _mali_uk_term_mem_s __user *uargs)
52 {
53     _mali_uk_term_mem_s kargs;
54     _mali_osk_errcode_t err;
55
56     MALI_CHECK_NON_NULL(uargs, -EINVAL);
57
58     kargs.ctx = session_data;
59     err = _mali_ukk_term_mem(&kargs);
60     if (_MALI_OSK_ERR_OK != err)
61     {
62         return map_errcode(err);
63     }
64
65     return 0;
66 }
67
68 int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user * argument)
69 {
70         _mali_uk_map_external_mem_s uk_args;
71         _mali_osk_errcode_t err_code;
72
73         /* validate input */
74         /* the session_data pointer was validated by caller */
75     MALI_CHECK_NON_NULL( argument, -EINVAL);
76
77         /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
78         if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_map_external_mem_s)) )
79         {
80                 return -EFAULT;
81         }
82
83     uk_args.ctx = session_data;
84         err_code = _mali_ukk_map_external_mem( &uk_args );
85
86     if (0 != put_user(uk_args.cookie, &argument->cookie))
87     {
88         if (_MALI_OSK_ERR_OK == err_code)
89         {
90             /* Rollback */
91                 _mali_uk_unmap_external_mem_s uk_args_unmap;
92
93             uk_args_unmap.ctx = session_data;
94             uk_args_unmap.cookie = uk_args.cookie;
95             err_code = _mali_ukk_unmap_external_mem( &uk_args_unmap );
96             if (_MALI_OSK_ERR_OK != err_code)
97             {
98                 MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_unmap_external_mem, as a result of failing put_user(), failed\n"));
99             }
100         }
101         return -EFAULT;
102     }
103
104     /* Return the error that _mali_ukk_free_big_block produced */
105         return map_errcode(err_code);
106 }
107
108 int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap_external_mem_s __user * argument)
109 {
110         _mali_uk_unmap_external_mem_s uk_args;
111         _mali_osk_errcode_t err_code;
112
113         /* validate input */
114         /* the session_data pointer was validated by caller */
115     MALI_CHECK_NON_NULL( argument, -EINVAL);
116
117         /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
118         if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_unmap_external_mem_s)) )
119         {
120                 return -EFAULT;
121         }
122
123     uk_args.ctx = session_data;
124         err_code = _mali_ukk_unmap_external_mem( &uk_args );
125
126         /* Return the error that _mali_ukk_free_big_block produced */
127         return map_errcode(err_code);
128 }
129
130 #if defined(CONFIG_MALI400_UMP)
131 int mem_release_ump_wrapper(struct mali_session_data *session_data, _mali_uk_release_ump_mem_s __user * argument)
132 {
133         _mali_uk_release_ump_mem_s uk_args;
134         _mali_osk_errcode_t err_code;
135
136         /* validate input */
137         /* the session_data pointer was validated by caller */
138     MALI_CHECK_NON_NULL( argument, -EINVAL);
139
140         /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
141         if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_release_ump_mem_s)) )
142         {
143                 return -EFAULT;
144         }
145
146     uk_args.ctx = session_data;
147         err_code = _mali_ukk_release_ump_mem( &uk_args );
148
149         /* Return the error that _mali_ukk_free_big_block produced */
150         return map_errcode(err_code);
151 }
152
153 int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_attach_ump_mem_s __user * argument)
154 {
155         _mali_uk_attach_ump_mem_s uk_args;
156         _mali_osk_errcode_t err_code;
157
158         /* validate input */
159         /* the session_data pointer was validated by caller */
160     MALI_CHECK_NON_NULL( argument, -EINVAL);
161
162         /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
163         if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_attach_ump_mem_s)) )
164         {
165                 return -EFAULT;
166         }
167
168     uk_args.ctx = session_data;
169         err_code = _mali_ukk_attach_ump_mem( &uk_args );
170
171     if (0 != put_user(uk_args.cookie, &argument->cookie))
172     {
173         if (_MALI_OSK_ERR_OK == err_code)
174         {
175             /* Rollback */
176                 _mali_uk_release_ump_mem_s uk_args_unmap;
177
178             uk_args_unmap.ctx = session_data;
179             uk_args_unmap.cookie = uk_args.cookie;
180             err_code = _mali_ukk_release_ump_mem( &uk_args_unmap );
181             if (_MALI_OSK_ERR_OK != err_code)
182             {
183                 MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_attach_mem, as a result of failing put_user(), failed\n"));
184             }
185         }
186         return -EFAULT;
187     }
188
189     /* Return the error that _mali_ukk_map_external_ump_mem produced */
190         return map_errcode(err_code);
191 }
192 #endif /* CONFIG_MALI400_UMP */
193
194 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)
195 {
196     _mali_uk_query_mmu_page_table_dump_size_s kargs;
197     _mali_osk_errcode_t err;
198
199     MALI_CHECK_NON_NULL(uargs, -EINVAL);
200     MALI_CHECK_NON_NULL(session_data, -EINVAL);
201
202     kargs.ctx = session_data;
203
204     err = _mali_ukk_query_mmu_page_table_dump_size(&kargs);
205     if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
206
207     if (0 != put_user(kargs.size, &uargs->size)) return -EFAULT;
208
209     return 0;
210 }
211
212 int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user * uargs)
213 {
214     _mali_uk_dump_mmu_page_table_s kargs;
215     _mali_osk_errcode_t err;
216     void *buffer;
217     int rc = -EFAULT;
218
219         /* validate input */
220     MALI_CHECK_NON_NULL(uargs, -EINVAL);
221         /* the session_data pointer was validated by caller */
222
223     kargs.buffer = NULL;
224
225     /* get location of user buffer */
226         if (0 != get_user(buffer, &uargs->buffer)) goto err_exit;
227         /* get size of mmu page table info buffer from user space */
228         if ( 0 != get_user(kargs.size, &uargs->size) ) goto err_exit;
229     /* verify we can access the whole of the user buffer */
230     if (!access_ok(VERIFY_WRITE, buffer, kargs.size)) goto err_exit;
231
232     /* allocate temporary buffer (kernel side) to store mmu page table info */
233     kargs.buffer = _mali_osk_valloc(kargs.size);
234     if (NULL == kargs.buffer)
235     {
236         rc = -ENOMEM;
237         goto err_exit;
238     }
239
240     kargs.ctx = session_data;
241     err = _mali_ukk_dump_mmu_page_table(&kargs);
242     if (_MALI_OSK_ERR_OK != err)
243     {
244         rc = map_errcode(err);
245         goto err_exit;
246     }
247
248     /* copy mmu page table info back to user space and update pointers */
249         if (0 != copy_to_user(uargs->buffer, kargs.buffer, kargs.size) ) goto err_exit;
250     if (0 != put_user((kargs.register_writes - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->register_writes)) goto err_exit;
251     if (0 != put_user((kargs.page_table_dump - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->page_table_dump)) goto err_exit;
252     if (0 != put_user(kargs.register_writes_size, &uargs->register_writes_size)) goto err_exit;
253     if (0 != put_user(kargs.page_table_dump_size, &uargs->page_table_dump_size)) goto err_exit;
254     rc = 0;
255
256 err_exit:
257     if (kargs.buffer) _mali_osk_vfree(kargs.buffer);
258     return rc;
259 }