blob: 951e1228c6e954eaa0a469be7facfaff852f0aa8
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 "gralloc_ion" |
21 | |
22 | #include <errno.h> |
23 | #include <fcntl.h> |
24 | #include <linux/ion.h> |
25 | #include <stdio.h> |
26 | #include <string.h> |
27 | #include <sys/ioctl.h> |
28 | #include <sys/mman.h> |
29 | #include <sys/types.h> |
30 | #include <unistd.h> |
31 | |
32 | #include <ion/ion.h> |
33 | #include <log/log.h> |
34 | |
35 | int ion_open() |
36 | { |
37 | int fd = open("/dev/ion", O_RDONLY | O_CLOEXEC); |
38 | if (fd < 0) |
39 | ALOGE("open /dev/ion failed!\n"); |
40 | return fd; |
41 | } |
42 | |
43 | int ion_close(int fd) |
44 | { |
45 | int ret = close(fd); |
46 | if (ret < 0) |
47 | return -errno; |
48 | return ret; |
49 | } |
50 | |
51 | static int ion_ioctl(int fd, int req, void *arg) |
52 | { |
53 | int ret = ioctl(fd, req, arg); |
54 | if (ret < 0) { |
55 | ALOGE("ioctl %x failed with code %d: %s\n", req, |
56 | ret, strerror(errno)); |
57 | return -errno; |
58 | } |
59 | return ret; |
60 | } |
61 | |
62 | int ion_alloc(int fd, size_t len, size_t align, unsigned int heap_mask, |
63 | unsigned int flags, ion_user_handle_t *handle) |
64 | { |
65 | int ret; |
66 | struct ion_allocation_data data = { |
67 | .len = len, |
68 | .align = align, |
69 | .heap_id_mask = heap_mask, |
70 | .flags = flags, |
71 | }; |
72 | |
73 | if (handle == NULL) |
74 | return -EINVAL; |
75 | |
76 | ret = ion_ioctl(fd, ION_IOC_ALLOC, &data); |
77 | if (ret < 0) |
78 | return ret; |
79 | *handle = data.handle; |
80 | return ret; |
81 | } |
82 | |
83 | int ion_free(int fd, ion_user_handle_t handle) |
84 | { |
85 | struct ion_handle_data data = { |
86 | .handle = handle, |
87 | }; |
88 | return ion_ioctl(fd, ION_IOC_FREE, &data); |
89 | } |
90 | |
91 | int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot, |
92 | int flags, off_t offset, unsigned char **ptr, int *map_fd) |
93 | { |
94 | int ret; |
95 | unsigned char *tmp_ptr; |
96 | struct ion_fd_data data = { |
97 | .handle = handle, |
98 | }; |
99 | |
100 | if (map_fd == NULL) |
101 | return -EINVAL; |
102 | if (ptr == NULL) |
103 | return -EINVAL; |
104 | |
105 | ret = ion_ioctl(fd, ION_IOC_MAP, &data); |
106 | if (ret < 0) |
107 | return ret; |
108 | if (data.fd < 0) { |
109 | ALOGE("map ioctl returned negative fd\n"); |
110 | return -EINVAL; |
111 | } |
112 | tmp_ptr = (unsigned char *)mmap(NULL, length, prot, flags, data.fd, offset); |
113 | if (tmp_ptr == MAP_FAILED) { |
114 | ALOGE("mmap failed: %s\n", strerror(errno)); |
115 | return -errno; |
116 | } |
117 | *map_fd = data.fd; |
118 | *ptr = tmp_ptr; |
119 | return ret; |
120 | } |
121 | |
122 | int ion_share(int fd, ion_user_handle_t handle, int *share_fd) |
123 | { |
124 | int ret; |
125 | struct ion_fd_data data = { |
126 | .handle = handle, |
127 | }; |
128 | |
129 | if (share_fd == NULL) |
130 | return -EINVAL; |
131 | |
132 | ret = ion_ioctl(fd, ION_IOC_SHARE, &data); |
133 | if (ret < 0) |
134 | return ret; |
135 | if (data.fd < 0) { |
136 | ALOGE("share ioctl returned negative fd\n"); |
137 | return -EINVAL; |
138 | } |
139 | *share_fd = data.fd; |
140 | return ret; |
141 | } |
142 | |
143 | int ion_alloc_fd(int fd, size_t len, size_t align, unsigned int heap_mask, |
144 | unsigned int flags, int *handle_fd) { |
145 | ion_user_handle_t handle; |
146 | int ret; |
147 | |
148 | ret = ion_alloc(fd, len, align, heap_mask, flags, &handle); |
149 | if (ret < 0) |
150 | return ret; |
151 | ret = ion_share(fd, handle, handle_fd); |
152 | ion_free(fd, handle); |
153 | return ret; |
154 | } |
155 | |
156 | int ion_import(int fd, int share_fd, ion_user_handle_t *handle) |
157 | { |
158 | int ret; |
159 | struct ion_fd_data data = { |
160 | .fd = share_fd, |
161 | }; |
162 | |
163 | if (handle == NULL) |
164 | return -EINVAL; |
165 | |
166 | ret = ion_ioctl(fd, ION_IOC_IMPORT, &data); |
167 | if (ret < 0) |
168 | return ret; |
169 | *handle = data.handle; |
170 | return ret; |
171 | } |
172 | |
173 | int ion_sync_fd(int fd, int handle_fd) |
174 | { |
175 | struct ion_fd_data data = { |
176 | .fd = handle_fd, |
177 | }; |
178 | return ion_ioctl(fd, ION_IOC_SYNC, &data); |
179 | } |
180 |