summaryrefslogtreecommitdiffstats
path: root/libion
diff options
context:
space:
mode:
authorLaura Abbott2017-06-30 00:55:50 -0500
committerSumit Semwal2017-08-09 23:00:38 -0500
commit30313f8bc08b60c32c1ee0cbca20186b11bb4c0a (patch)
treee53fe95e7318cc5361b7ee7aa80d2e66bd178586 /libion
parent89b8de2994d8bb809b2e2749154b9456ed096a8d (diff)
downloadplatform-system-core-30313f8bc08b60c32c1ee0cbca20186b11bb4c0a.tar.gz
platform-system-core-30313f8bc08b60c32c1ee0cbca20186b11bb4c0a.tar.xz
platform-system-core-30313f8bc08b60c32c1ee0cbca20186b11bb4c0a.zip
libion: Adapt to new ION interface
4.12+ kernels have substantially different ION interface. Adapt libion to the new one. In doing so, for sake of clarity, rename ION_IOC_ALLOC to ION_IOC_NEW_ALLOC the to denote new mechanism. An ion_is_legacy() is provided to check whether the kernel supports old ION interface or new. Userspace has the responsibility to use it accordingly. Devices using kernels without the 4.12 ION updates, can continue to use libion as before, and will have no impact. Only devices using libion with 4.12+ kernels (or kernels with backported ION updates) will need to update their users of libion, including gralloc. Test: validated with hikey gralloc, with both old and new kernels Signed-off-by: Laura Abbott <labbott@redhat.com> Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org> [sumits: keep old abi compatibility] Change-Id: I7899af9e812d0cf5e73b443a3f0248118b42a382
Diffstat (limited to 'libion')
-rw-r--r--libion/include/ion/ion.h9
-rw-r--r--libion/ion.c158
2 files changed, 109 insertions, 58 deletions
diff --git a/libion/include/ion/ion.h b/libion/include/ion/ion.h
index f47793d27..a60d24eaf 100644
--- a/libion/include/ion/ion.h
+++ b/libion/include/ion/ion.h
@@ -41,6 +41,15 @@ int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot,
41int ion_share(int fd, ion_user_handle_t handle, int *share_fd); 41int ion_share(int fd, ion_user_handle_t handle, int *share_fd);
42int ion_import(int fd, int share_fd, ion_user_handle_t *handle); 42int ion_import(int fd, int share_fd, ion_user_handle_t *handle);
43 43
44/**
45 * Add 4.12+ kernel ION interfaces here for forward compatibility
46 * This should be needed till the pre-4.12+ ION interfaces are backported.
47 */
48int ion_query_heap_cnt(int fd, int* cnt);
49int ion_query_get_heaps(int fd, int cnt, void* buffers);
50
51int ion_is_legacy(int fd);
52
44__END_DECLS 53__END_DECLS
45 54
46#endif /* __SYS_CORE_ION_H */ 55#endif /* __SYS_CORE_ION_H */
diff --git a/libion/ion.c b/libion/ion.c
index 9aaa6f28e..583612854 100644
--- a/libion/ion.c
+++ b/libion/ion.c
@@ -22,6 +22,7 @@
22#include <errno.h> 22#include <errno.h>
23#include <fcntl.h> 23#include <fcntl.h>
24#include <linux/ion.h> 24#include <linux/ion.h>
25#include <stdatomic.h>
25#include <stdio.h> 26#include <stdio.h>
26#include <string.h> 27#include <string.h>
27#include <sys/ioctl.h> 28#include <sys/ioctl.h>
@@ -30,81 +31,89 @@
30#include <unistd.h> 31#include <unistd.h>
31 32
32#include <ion/ion.h> 33#include <ion/ion.h>
34#include "ion_4.12.h"
35
33#include <log/log.h> 36#include <log/log.h>
34 37
35int ion_open() 38enum ion_version { ION_VERSION_UNKNOWN, ION_VERSION_MODERN, ION_VERSION_LEGACY };
36{ 39
40static atomic_int g_ion_version = ATOMIC_VAR_INIT(ION_VERSION_UNKNOWN);
41
42int ion_is_legacy(int fd) {
43 int version = atomic_load_explicit(&g_ion_version, memory_order_acquire);
44 if (version == ION_VERSION_UNKNOWN) {
45 /**
46 * Check for FREE IOCTL here; it is available only in the old
47 * kernels, not the new ones.
48 */
49 int err = ion_free(fd, (ion_user_handle_t)NULL);
50 version = (err == -ENOTTY) ? ION_VERSION_MODERN : ION_VERSION_LEGACY;
51 atomic_store_explicit(&g_ion_version, version, memory_order_release);
52 }
53 return version == ION_VERSION_LEGACY;
54}
55
56int ion_open() {
37 int fd = open("/dev/ion", O_RDONLY | O_CLOEXEC); 57 int fd = open("/dev/ion", O_RDONLY | O_CLOEXEC);
38 if (fd < 0) 58 if (fd < 0) ALOGE("open /dev/ion failed!\n");
39 ALOGE("open /dev/ion failed!\n"); 59
40 return fd; 60 return fd;
41} 61}
42 62
43int ion_close(int fd) 63int ion_close(int fd) {
44{
45 int ret = close(fd); 64 int ret = close(fd);
46 if (ret < 0) 65 if (ret < 0) return -errno;
47 return -errno;
48 return ret; 66 return ret;
49} 67}
50 68
51static int ion_ioctl(int fd, int req, void *arg) 69static int ion_ioctl(int fd, int req, void* arg) {
52{
53 int ret = ioctl(fd, req, arg); 70 int ret = ioctl(fd, req, arg);
54 if (ret < 0) { 71 if (ret < 0) {
55 ALOGE("ioctl %x failed with code %d: %s\n", req, 72 ALOGE("ioctl %x failed with code %d: %s\n", req, ret, strerror(errno));
56 ret, strerror(errno));
57 return -errno; 73 return -errno;
58 } 74 }
59 return ret; 75 return ret;
60} 76}
61 77
62int ion_alloc(int fd, size_t len, size_t align, unsigned int heap_mask, 78int ion_alloc(int fd, size_t len, size_t align, unsigned int heap_mask, unsigned int flags,
63 unsigned int flags, ion_user_handle_t *handle) 79 ion_user_handle_t* handle) {
64{ 80 int ret = 0;
65 int ret; 81
82 if ((handle == NULL) || (!ion_is_legacy(fd))) return -EINVAL;
83
66 struct ion_allocation_data data = { 84 struct ion_allocation_data data = {
67 .len = len, 85 .len = len, .align = align, .heap_id_mask = heap_mask, .flags = flags,
68 .align = align,
69 .heap_id_mask = heap_mask,
70 .flags = flags,
71 }; 86 };
72 87
73 if (handle == NULL)
74 return -EINVAL;
75
76 ret = ion_ioctl(fd, ION_IOC_ALLOC, &data); 88 ret = ion_ioctl(fd, ION_IOC_ALLOC, &data);
77 if (ret < 0) 89 if (ret < 0) return ret;
78 return ret; 90
79 *handle = data.handle; 91 *handle = data.handle;
92
80 return ret; 93 return ret;
81} 94}
82 95
83int ion_free(int fd, ion_user_handle_t handle) 96int ion_free(int fd, ion_user_handle_t handle) {
84{
85 struct ion_handle_data data = { 97 struct ion_handle_data data = {
86 .handle = handle, 98 .handle = handle,
87 }; 99 };
88 return ion_ioctl(fd, ION_IOC_FREE, &data); 100 return ion_ioctl(fd, ION_IOC_FREE, &data);
89} 101}
90 102
91int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot, 103int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot, int flags, off_t offset,
92 int flags, off_t offset, unsigned char **ptr, int *map_fd) 104 unsigned char** ptr, int* map_fd) {
93{ 105 if (!ion_is_legacy(fd)) return -EINVAL;
94 int ret; 106 int ret;
95 unsigned char *tmp_ptr; 107 unsigned char* tmp_ptr;
96 struct ion_fd_data data = { 108 struct ion_fd_data data = {
97 .handle = handle, 109 .handle = handle,
98 }; 110 };
99 111
100 if (map_fd == NULL) 112 if (map_fd == NULL) return -EINVAL;
101 return -EINVAL; 113 if (ptr == NULL) return -EINVAL;
102 if (ptr == NULL)
103 return -EINVAL;
104 114
105 ret = ion_ioctl(fd, ION_IOC_MAP, &data); 115 ret = ion_ioctl(fd, ION_IOC_MAP, &data);
106 if (ret < 0) 116 if (ret < 0) return ret;
107 return ret;
108 if (data.fd < 0) { 117 if (data.fd < 0) {
109 ALOGE("map ioctl returned negative fd\n"); 118 ALOGE("map ioctl returned negative fd\n");
110 return -EINVAL; 119 return -EINVAL;
@@ -119,19 +128,17 @@ int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot,
119 return ret; 128 return ret;
120} 129}
121 130
122int ion_share(int fd, ion_user_handle_t handle, int *share_fd) 131int ion_share(int fd, ion_user_handle_t handle, int* share_fd) {
123{
124 int ret; 132 int ret;
125 struct ion_fd_data data = { 133 struct ion_fd_data data = {
126 .handle = handle, 134 .handle = handle,
127 }; 135 };
128 136
129 if (share_fd == NULL) 137 if (!ion_is_legacy(fd)) return -EINVAL;
130 return -EINVAL; 138 if (share_fd == NULL) return -EINVAL;
131 139
132 ret = ion_ioctl(fd, ION_IOC_SHARE, &data); 140 ret = ion_ioctl(fd, ION_IOC_SHARE, &data);
133 if (ret < 0) 141 if (ret < 0) return ret;
134 return ret;
135 if (data.fd < 0) { 142 if (data.fd < 0) {
136 ALOGE("share ioctl returned negative fd\n"); 143 ALOGE("share ioctl returned negative fd\n");
137 return -EINVAL; 144 return -EINVAL;
@@ -140,40 +147,75 @@ int ion_share(int fd, ion_user_handle_t handle, int *share_fd)
140 return ret; 147 return ret;
141} 148}
142 149
143int ion_alloc_fd(int fd, size_t len, size_t align, unsigned int heap_mask, 150int ion_alloc_fd(int fd, size_t len, size_t align, unsigned int heap_mask, unsigned int flags,
144 unsigned int flags, int *handle_fd) { 151 int* handle_fd) {
145 ion_user_handle_t handle; 152 ion_user_handle_t handle;
146 int ret; 153 int ret;
147 154
148 ret = ion_alloc(fd, len, align, heap_mask, flags, &handle); 155 if (!ion_is_legacy(fd)) {
149 if (ret < 0) 156 struct ion_new_allocation_data data = {
150 return ret; 157 .len = len,
151 ret = ion_share(fd, handle, handle_fd); 158 .heap_id_mask = heap_mask,
152 ion_free(fd, handle); 159 .flags = flags,
160 };
161
162 ret = ion_ioctl(fd, ION_IOC_NEW_ALLOC, &data);
163 if (ret < 0) return ret;
164 *handle_fd = data.fd;
165 } else {
166 ret = ion_alloc(fd, len, align, heap_mask, flags, &handle);
167 if (ret < 0) return ret;
168 ret = ion_share(fd, handle, handle_fd);
169 ion_free(fd, handle);
170 }
153 return ret; 171 return ret;
154} 172}
155 173
156int ion_import(int fd, int share_fd, ion_user_handle_t *handle) 174int ion_import(int fd, int share_fd, ion_user_handle_t* handle) {
157{
158 int ret; 175 int ret;
159 struct ion_fd_data data = { 176 struct ion_fd_data data = {
160 .fd = share_fd, 177 .fd = share_fd,
161 }; 178 };
162 179
163 if (handle == NULL) 180 if (!ion_is_legacy(fd)) return -EINVAL;
164 return -EINVAL; 181
182 if (handle == NULL) return -EINVAL;
165 183
166 ret = ion_ioctl(fd, ION_IOC_IMPORT, &data); 184 ret = ion_ioctl(fd, ION_IOC_IMPORT, &data);
167 if (ret < 0) 185 if (ret < 0) return ret;
168 return ret;
169 *handle = data.handle; 186 *handle = data.handle;
170 return ret; 187 return ret;
171} 188}
172 189
173int ion_sync_fd(int fd, int handle_fd) 190int ion_sync_fd(int fd, int handle_fd) {
174{
175 struct ion_fd_data data = { 191 struct ion_fd_data data = {
176 .fd = handle_fd, 192 .fd = handle_fd,
177 }; 193 };
194
195 if (!ion_is_legacy(fd)) return -EINVAL;
196
178 return ion_ioctl(fd, ION_IOC_SYNC, &data); 197 return ion_ioctl(fd, ION_IOC_SYNC, &data);
179} 198}
199
200int ion_query_heap_cnt(int fd, int* cnt) {
201 int ret;
202 struct ion_heap_query query;
203
204 memset(&query, 0, sizeof(query));
205
206 ret = ion_ioctl(fd, ION_IOC_HEAP_QUERY, &query);
207 if (ret < 0) return ret;
208
209 *cnt = query.cnt;
210 return ret;
211}
212
213int ion_query_get_heaps(int fd, int cnt, void* buffers) {
214 int ret;
215 struct ion_heap_query query = {
216 .cnt = cnt, .heaps = (uintptr_t)buffers,
217 };
218
219 ret = ion_ioctl(fd, ION_IOC_HEAP_QUERY, &query);
220 return ret;
221}