1 /*
2 * ion.c
3 *
4 * Memory Allocator functions for ion
5 *
6 * Copyright 2011 Google, Inc
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20 #define LOG_TAG "ion"
21
22 #include <cutils/log.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <stdio.h>
26 #include <sys/ioctl.h>
27 #include <sys/mman.h>
28 #include <sys/types.h>
29
30 #include <linux/ion.h>
31 #include <ion/ion.h>
32
ion_open()33 int ion_open()
34 {
35 int fd = open("/dev/ion", O_RDWR);
36 if (fd < 0)
37 ALOGE("open /dev/ion failed!\n");
38 return fd;
39 }
40
ion_close(int fd)41 int ion_close(int fd)
42 {
43 return close(fd);
44 }
45
ion_ioctl(int fd,int req,void * arg)46 static int ion_ioctl(int fd, int req, void *arg)
47 {
48 int ret = ioctl(fd, req, arg);
49 if (ret < 0) {
50 ALOGE("ioctl %d failed with code %d: %s\n", req,
51 ret, strerror(errno));
52 return -errno;
53 }
54 return ret;
55 }
56
ion_alloc(int fd,size_t len,size_t align,unsigned int flags,struct ion_handle ** handle)57 int ion_alloc(int fd, size_t len, size_t align,
58 unsigned int flags, struct ion_handle **handle)
59 {
60 int ret;
61 struct ion_allocation_data data = {
62 .len = len,
63 .align = align,
64 .flags = flags,
65 };
66
67 ret = ion_ioctl(fd, ION_IOC_ALLOC, &data);
68 if (ret < 0)
69 return ret;
70 *handle = data.handle;
71 return ret;
72 }
73
ion_alloc_tiler(int fd,size_t w,size_t h,int fmt,unsigned int flags,struct ion_handle ** handle,size_t * stride)74 int ion_alloc_tiler(int fd, size_t w, size_t h, int fmt, unsigned int flags,
75 struct ion_handle **handle, size_t *stride)
76 {
77 int ret;
78 struct omap_ion_tiler_alloc_data alloc_data = {
79 .w = w,
80 .h = h,
81 .fmt = fmt,
82 .flags = flags,
83 .out_align = PAGE_SIZE,
84 .token = 0,
85 };
86
87 struct ion_custom_data custom_data = {
88 .cmd = OMAP_ION_TILER_ALLOC,
89 .arg = (unsigned long)(&alloc_data),
90 };
91
92 ret = ion_ioctl(fd, ION_IOC_CUSTOM, &custom_data);
93 if (ret < 0)
94 return ret;
95 *stride = alloc_data.stride;
96 *handle = alloc_data.handle;
97 return ret;
98 }
99
ion_free(int fd,struct ion_handle * handle)100 int ion_free(int fd, struct ion_handle *handle)
101 {
102 struct ion_handle_data data = {
103 .handle = handle,
104 };
105 return ion_ioctl(fd, ION_IOC_FREE, &data);
106 }
107
ion_map(int fd,struct ion_handle * handle,size_t length,int prot,int flags,off_t offset,unsigned char ** ptr,int * map_fd)108 int ion_map(int fd, struct ion_handle *handle, size_t length, int prot,
109 int flags, off_t offset, unsigned char **ptr, int *map_fd)
110 {
111 struct ion_fd_data data = {
112 .handle = handle,
113 };
114 int ret = ion_ioctl(fd, ION_IOC_MAP, &data);
115 if (ret < 0)
116 return ret;
117 *map_fd = data.fd;
118 if (*map_fd < 0) {
119 ALOGE("map ioctl returned negative fd\n");
120 return -EINVAL;
121 }
122 *ptr = mmap(NULL, length, prot, flags, *map_fd, offset);
123 if (*ptr == MAP_FAILED) {
124 ALOGE("mmap failed: %s\n", strerror(errno));
125 return -errno;
126 }
127 return ret;
128 }
129
ion_share(int fd,struct ion_handle * handle,int * share_fd)130 int ion_share(int fd, struct ion_handle *handle, int *share_fd)
131 {
132 int map_fd;
133 struct ion_fd_data data = {
134 .handle = handle,
135 };
136 int ret = ion_ioctl(fd, ION_IOC_SHARE, &data);
137 if (ret < 0)
138 return ret;
139 *share_fd = data.fd;
140 if (*share_fd < 0) {
141 ALOGE("map ioctl returned negative fd\n");
142 return -EINVAL;
143 }
144 return ret;
145 }
146
ion_import(int fd,int share_fd,struct ion_handle ** handle)147 int ion_import(int fd, int share_fd, struct ion_handle **handle)
148 {
149 struct ion_fd_data data = {
150 .fd = share_fd,
151 };
152 int ret = ion_ioctl(fd, ION_IOC_IMPORT, &data);
153 if (ret < 0)
154 return ret;
155 *handle = data.handle;
156 return ret;
157 }
158
159 #if 0
160 int ion_sync_fd(int fd, int handle_fd)
161 {
162 struct ion_fd_data data = {
163 .fd = handle_fd,
164 };
165 return ion_ioctl(fd, ION_IOC_SYNC, &data);
166 }
167 #endif
168
ion_map_cacheable(int fd,struct ion_handle * handle,size_t length,int prot,int flags,off_t offset,unsigned char ** ptr,int * map_fd)169 int ion_map_cacheable(int fd, struct ion_handle *handle, size_t length, int prot,
170 int flags, off_t offset, unsigned char **ptr, int *map_fd)
171 {
172 struct ion_fd_data data = {
173 .handle = handle,
174 .cacheable = 1,
175 };
176 int ret = ion_ioctl(fd, ION_IOC_MAP, &data);
177 if (ret < 0)
178 return ret;
179 *map_fd = data.fd;
180 if (*map_fd < 0) {
181 ALOGE("map ioctl returned negative fd\n");
182 return -EINVAL;
183 }
184 *ptr = mmap(NULL, length, prot, flags, *map_fd, offset);
185 if (*ptr == MAP_FAILED) {
186 ALOGE("mmap failed: %s\n", strerror(errno));
187 return -errno;
188 }
189 return ret;
190 }
191
ion_flush_cached(int fd,struct ion_handle * handle,size_t length,unsigned char * ptr)192 int ion_flush_cached(int fd, struct ion_handle *handle, size_t length,
193 unsigned char *ptr)
194 {
195 struct ion_cached_user_buf_data data = {
196 .handle = handle,
197 .vaddr = (unsigned long)ptr,
198 .size = length,
199 };
200 return ion_ioctl(fd, ION_IOC_FLUSH_CACHED, &data);
201 }
202
ion_inval_cached(int fd,struct ion_handle * handle,size_t length,unsigned char * ptr)203 int ion_inval_cached(int fd, struct ion_handle *handle, size_t length,
204 unsigned char *ptr)
205 {
206 struct ion_cached_user_buf_data data = {
207 .handle = handle,
208 .vaddr = (unsigned long)ptr,
209 .size = length,
210 };
211 return ion_ioctl(fd, ION_IOC_INVAL_CACHED, &data);
212 }
213