tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / staging / android / ion / compat_ion.c
1 /*
2  * drivers/gpu/ion/compat_ion.c
3  *
4  * Copyright (C) 2013 Google, Inc.
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  */
16
17 #include <linux/compat.h>
18 #include <linux/fs.h>
19 #include <linux/uaccess.h>
20
21 #include "ion.h"
22 #include "compat_ion.h"
23 #include "sprd/compat_sprd_ion.h"
24
25 /* See drivers/staging/android/uapi/ion.h for the definition of these structs */
26 struct compat_ion_allocation_data {
27         compat_size_t len;
28         compat_size_t align;
29         compat_uint_t heap_id_mask;
30         compat_uint_t flags;
31         compat_int_t handle;
32 };
33
34 struct compat_ion_custom_data {
35         compat_uint_t cmd;
36         compat_ulong_t arg;
37 };
38
39 struct compat_ion_handle_data {
40         compat_int_t handle;
41 };
42
43 #define COMPAT_ION_IOC_ALLOC    _IOWR(ION_IOC_MAGIC, 0, \
44                                       struct compat_ion_allocation_data)
45 #define COMPAT_ION_IOC_FREE     _IOWR(ION_IOC_MAGIC, 1, \
46                                       struct compat_ion_handle_data)
47 #define COMPAT_ION_IOC_CUSTOM   _IOWR(ION_IOC_MAGIC, 6, \
48                                       struct compat_ion_custom_data)
49
50 static int compat_get_ion_allocation_data(
51                         struct compat_ion_allocation_data __user *data32,
52                         struct ion_allocation_data __user *data)
53 {
54         compat_size_t s;
55         compat_uint_t u;
56         compat_int_t i;
57         int err;
58
59         err = get_user(s, &data32->len);
60         err |= put_user(s, &data->len);
61         err |= get_user(s, &data32->align);
62         err |= put_user(s, &data->align);
63         err |= get_user(u, &data32->heap_id_mask);
64         err |= put_user(u, &data->heap_id_mask);
65         err |= get_user(u, &data32->flags);
66         err |= put_user(u, &data->flags);
67         err |= get_user(i, &data32->handle);
68         err |= put_user(i, &data->handle);
69
70         return err;
71 }
72
73 static int compat_get_ion_handle_data(
74                         struct compat_ion_handle_data __user *data32,
75                         struct ion_handle_data __user *data)
76 {
77         compat_int_t i;
78         int err;
79
80         err = get_user(i, &data32->handle);
81         err |= put_user(i, &data->handle);
82
83         return err;
84 }
85
86 static int compat_put_ion_allocation_data(
87                         struct compat_ion_allocation_data __user *data32,
88                         struct ion_allocation_data __user *data)
89 {
90         compat_size_t s;
91         compat_uint_t u;
92         compat_int_t i;
93         int err;
94
95         err = get_user(s, &data->len);
96         err |= put_user(s, &data32->len);
97         err |= get_user(s, &data->align);
98         err |= put_user(s, &data32->align);
99         err |= get_user(u, &data->heap_id_mask);
100         err |= put_user(u, &data32->heap_id_mask);
101         err |= get_user(u, &data->flags);
102         err |= put_user(u, &data32->flags);
103         err |= get_user(i, &data->handle);
104         err |= put_user(i, &data32->handle);
105
106         return err;
107 }
108
109 static int compat_get_ion_custom_data(
110                         struct compat_ion_custom_data __user *data32,
111                         struct ion_custom_data __user *data)
112 {
113         compat_uint_t cmd;
114         compat_ulong_t arg;
115         int err;
116
117         err = get_user(cmd, &data32->cmd);
118         err |= put_user(cmd, &data->cmd);
119         err |= get_user(arg, &data32->arg);
120         err |= put_user(arg, &data->arg);
121
122         return err;
123 };
124
125 long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
126 {
127         long ret;
128
129         if (!filp->f_op || !filp->f_op->unlocked_ioctl)
130                 return -ENOTTY;
131
132         switch (cmd) {
133         case COMPAT_ION_IOC_ALLOC:
134         {
135                 struct compat_ion_allocation_data __user *data32;
136                 struct ion_allocation_data __user *data;
137                 int err;
138
139                 data32 = compat_ptr(arg);
140                 data = compat_alloc_user_space(sizeof(*data));
141                 if (data == NULL)
142                         return -EFAULT;
143
144                 err = compat_get_ion_allocation_data(data32, data);
145                 if (err)
146                         return err;
147                 ret = filp->f_op->unlocked_ioctl(filp, ION_IOC_ALLOC,
148                                                         (unsigned long)data);
149                 err = compat_put_ion_allocation_data(data32, data);
150                 return ret ? ret : err;
151         }
152         case COMPAT_ION_IOC_FREE:
153         {
154                 struct compat_ion_handle_data __user *data32;
155                 struct ion_handle_data __user *data;
156                 int err;
157
158                 data32 = compat_ptr(arg);
159                 data = compat_alloc_user_space(sizeof(*data));
160                 if (data == NULL)
161                         return -EFAULT;
162
163                 err = compat_get_ion_handle_data(data32, data);
164                 if (err)
165                         return err;
166
167                 return filp->f_op->unlocked_ioctl(filp, ION_IOC_FREE,
168                                                         (unsigned long)data);
169         }
170         case COMPAT_ION_IOC_CUSTOM: {
171                 struct compat_ion_custom_data __user *data32;
172                 struct ion_custom_data __user *data;
173                 int err;
174
175                 data32 = compat_ptr(arg);
176                 data = compat_alloc_user_space(sizeof(*data));
177                 if (data == NULL)
178                         return -EFAULT;
179
180                 err = compat_get_ion_custom_data(data32, data);
181                 if (err)
182                         return err;
183                 if (compat_sprd_ion_ioctl)
184                         return compat_sprd_ion_ioctl(filp, data->cmd, data->arg);
185                 else
186                         return filp->f_op->unlocked_ioctl(filp, ION_IOC_CUSTOM,
187                                                                 (unsigned long)data);
188         }
189         case ION_IOC_SHARE:
190         case ION_IOC_MAP:
191         case ION_IOC_IMPORT:
192         case ION_IOC_SYNC:
193         case ION_IOC_INVALIDATE:
194                 return filp->f_op->unlocked_ioctl(filp, cmd,
195                                                 (unsigned long)compat_ptr(arg));
196         default:
197                 return -ENOIOCTLCMD;
198         }
199 }