blob: f327818ba60bf7a1072f610cfc1965d37258ed7a [file] [log] [blame]
Prabhanjan Kandula96e92342016-03-24 21:03:35 +05301/*
Rohit Kulkarni3ac98392017-10-20 12:04:34 -07002 * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
Prabhanjan Kandula96e92342016-03-24 21:03:35 +05303
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#define DEBUG 0
31#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
32#include <sys/ioctl.h>
33#include <sys/mman.h>
Rohit Kulkarni3ac98392017-10-20 12:04:34 -070034#include <linux/msm_ion.h>
35#if TARGET_ION_ABI_VERSION >= 2
Rohit Kulkarni3ac98392017-10-20 12:04:34 -070036#include <linux/dma-buf.h>
Naseer Ahmede36f2242017-12-01 15:33:56 -050037#include <ion/ion.h>
Rohit Kulkarni3ac98392017-10-20 12:04:34 -070038#endif
Prabhanjan Kandula96e92342016-03-24 21:03:35 +053039#include <stdlib.h>
40#include <fcntl.h>
41#include <cutils/log.h>
Naseer Ahmede36f2242017-12-01 15:33:56 -050042#include <cutils/trace.h>
Prabhanjan Kandula96e92342016-03-24 21:03:35 +053043#include <errno.h>
44#include <utils/Trace.h>
Naseer Ahmed7a2b09c2017-05-11 13:03:17 -040045#include <string>
Prabhanjan Kandula96e92342016-03-24 21:03:35 +053046
Prabhanjan Kandula96e92342016-03-24 21:03:35 +053047#include "gr_utils.h"
Naseer Ahmede36f2242017-12-01 15:33:56 -050048#include "gralloc_priv.h"
Prabhanjan Kandula96e92342016-03-24 21:03:35 +053049#include "gr_ion_alloc.h"
50
Naseer Ahmede36f2242017-12-01 15:33:56 -050051namespace gralloc {
Prabhanjan Kandula96e92342016-03-24 21:03:35 +053052
53bool IonAlloc::Init() {
54 if (ion_dev_fd_ == FD_INIT) {
Rohit Kulkarni3ac98392017-10-20 12:04:34 -070055 ion_dev_fd_ = OpenIonDevice();
Prabhanjan Kandula96e92342016-03-24 21:03:35 +053056 }
57
58 if (ion_dev_fd_ < 0) {
59 ALOGE("%s: Failed to open ion device - %s", __FUNCTION__, strerror(errno));
60 ion_dev_fd_ = FD_INIT;
61 return false;
62 }
63
64 return true;
65}
66
Rohit Kulkarni3ac98392017-10-20 12:04:34 -070067#if TARGET_ION_ABI_VERSION >= 2 // Use libion APIs for new ion
68
69int IonAlloc::OpenIonDevice() {
70 return ion_open();
71}
72
73void IonAlloc::CloseIonDevice() {
74 if (ion_dev_fd_ > FD_INIT) {
75 ion_close(ion_dev_fd_);
76 }
77
78 ion_dev_fd_ = FD_INIT;
79}
80
81int IonAlloc::AllocBuffer(AllocData *data) {
82 ATRACE_CALL();
83 int err = 0;
84 int fd = -1;
85 unsigned int flags = data->flags;
86
87 flags |= data->uncached ? 0 : ION_FLAG_CACHED;
88
89 std::string tag_name{};
90 if (ATRACE_ENABLED()) {
91 tag_name = "libion alloc size: " + std::to_string(data->size);
92 }
93
94 ATRACE_BEGIN(tag_name.c_str());
95 err = ion_alloc_fd(ion_dev_fd_, data->size, data->align, data->heap_id, flags, &fd);
96 ATRACE_END();
97 if (err) {
98 ALOGE("libion alloc failed");
99 return err;
100 }
101
102 data->fd = fd;
103 data->ion_handle = fd; // For new ion api ion_handle does not exists so reusing fd for now
104 ALOGD_IF(DEBUG, "libion: Allocated buffer size:%u fd:%d", data->size, data->fd);
105
106 return 0;
107}
108
109int IonAlloc::FreeBuffer(void *base, unsigned int size, unsigned int offset, int fd,
110 int /*ion_handle*/) {
111 ATRACE_CALL();
112 int err = 0;
113 ALOGD_IF(DEBUG, "libion: Freeing buffer base:%p size:%u fd:%d", base, size, fd);
114
115 if (base) {
116 err = UnmapBuffer(base, size, offset);
117 }
118
119 close(fd);
120 return err;
121}
122
123int IonAlloc::ImportBuffer(int fd) {
124 // For new ion api ion_handle does not exists so reusing fd for now
125 return fd;
126}
127
128int IonAlloc::CleanBuffer(void */*base*/, unsigned int /*size*/, unsigned int /*offset*/,
129 int /*handle*/, int op, int dma_buf_fd) {
130 ATRACE_CALL();
131 ATRACE_INT("operation id", op);
132
133 struct dma_buf_sync sync;
134 int err = 0;
135
136 switch (op) {
137 case CACHE_CLEAN:
138 sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
139 break;
140 case CACHE_INVALIDATE:
141 sync.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW;
142 break;
143 default:
144 ALOGE("%s: Invalid operation %d", __FUNCTION__, op);
145 return -1;
146 }
147
148 if (ioctl(dma_buf_fd, INT(DMA_BUF_IOCTL_SYNC), &sync)) {
149 err = -errno;
150 ALOGE("%s: DMA_BUF_IOCTL_SYNC failed with error - %s", __FUNCTION__, strerror(errno));
151 return err;
152 }
153
154 return 0;
155}
156
157#else
158#ifndef TARGET_ION_ABI_VERSION // Use old ion apis directly
159
160int IonAlloc::OpenIonDevice() {
161 return open(kIonDevice, O_RDONLY);
162}
163
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530164void IonAlloc::CloseIonDevice() {
165 if (ion_dev_fd_ > FD_INIT) {
166 close(ion_dev_fd_);
167 }
168
169 ion_dev_fd_ = FD_INIT;
170}
171
172int IonAlloc::AllocBuffer(AllocData *data) {
173 ATRACE_CALL();
174 int err = 0;
175 struct ion_handle_data handle_data;
176 struct ion_fd_data fd_data;
177 struct ion_allocation_data ion_alloc_data;
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530178
179 ion_alloc_data.len = data->size;
180 ion_alloc_data.align = data->align;
181 ion_alloc_data.heap_id_mask = data->heap_id;
182 ion_alloc_data.flags = data->flags;
183 ion_alloc_data.flags |= data->uncached ? 0 : ION_FLAG_CACHED;
Naseer Ahmed7a2b09c2017-05-11 13:03:17 -0400184 std::string tag_name{};
185 if (ATRACE_ENABLED()) {
186 tag_name = "ION_IOC_ALLOC size: " + std::to_string(data->size);
187 }
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530188
Naseer Ahmed7a2b09c2017-05-11 13:03:17 -0400189 ATRACE_BEGIN(tag_name.c_str());
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530190 if (ioctl(ion_dev_fd_, INT(ION_IOC_ALLOC), &ion_alloc_data)) {
191 err = -errno;
192 ALOGE("ION_IOC_ALLOC failed with error - %s", strerror(errno));
193 return err;
194 }
Naseer Ahmed7a2b09c2017-05-11 13:03:17 -0400195 ATRACE_END();
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530196
197 fd_data.handle = ion_alloc_data.handle;
198 handle_data.handle = ion_alloc_data.handle;
Naseer Ahmed7a2b09c2017-05-11 13:03:17 -0400199 ATRACE_BEGIN("ION_IOC_MAP");
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530200 if (ioctl(ion_dev_fd_, INT(ION_IOC_MAP), &fd_data)) {
201 err = -errno;
202 ALOGE("%s: ION_IOC_MAP failed with error - %s", __FUNCTION__, strerror(errno));
203 ioctl(ion_dev_fd_, INT(ION_IOC_FREE), &handle_data);
204 return err;
205 }
Naseer Ahmed7a2b09c2017-05-11 13:03:17 -0400206 ATRACE_END();
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530207
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530208 data->fd = fd_data.fd;
Naseer Ahmede69031e2016-11-22 20:05:16 -0500209 data->ion_handle = handle_data.handle;
Naseer Ahmede36f2242017-12-01 15:33:56 -0500210 ALOGD_IF(DEBUG, "ion: Allocated buffer size:%zu fd:%d handle:0x%x", ion_alloc_data.len, data->fd,
211 data->ion_handle);
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530212
213 return 0;
214}
215
Naseer Ahmede69031e2016-11-22 20:05:16 -0500216int IonAlloc::FreeBuffer(void *base, unsigned int size, unsigned int offset, int fd,
217 int ion_handle) {
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530218 ATRACE_CALL();
219 int err = 0;
Naseer Ahmede69031e2016-11-22 20:05:16 -0500220 ALOGD_IF(DEBUG, "ion: Freeing buffer base:%p size:%u fd:%d handle:0x%x", base, size, fd,
221 ion_handle);
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530222
223 if (base) {
224 err = UnmapBuffer(base, size, offset);
225 }
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530226
Naseer Ahmed3a9d53a2017-03-15 19:21:40 -0400227 if (ion_handle > 0) {
228 struct ion_handle_data handle_data;
229 handle_data.handle = ion_handle;
230 ioctl(ion_dev_fd_, INT(ION_IOC_FREE), &handle_data);
231 }
232 close(fd);
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530233 return err;
234}
235
Naseer Ahmed3a9d53a2017-03-15 19:21:40 -0400236int IonAlloc::ImportBuffer(int fd) {
237 struct ion_fd_data fd_data;
238 int err = 0;
239 fd_data.fd = fd;
240 if (ioctl(ion_dev_fd_, INT(ION_IOC_IMPORT), &fd_data)) {
241 err = -errno;
242 ALOGE("%s: ION_IOC_IMPORT failed with error - %s", __FUNCTION__, strerror(errno));
243 return err;
244 }
245 return fd_data.handle;
246}
247
Rohit Kulkarni3ac98392017-10-20 12:04:34 -0700248int IonAlloc::CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op,
249 int /*fd*/) {
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530250 ATRACE_CALL();
251 ATRACE_INT("operation id", op);
252 struct ion_flush_data flush_data;
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530253 int err = 0;
254
Naseer Ahmed3a9d53a2017-03-15 19:21:40 -0400255 flush_data.handle = handle;
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530256 flush_data.vaddr = base;
257 // offset and length are unsigned int
258 flush_data.offset = offset;
259 flush_data.length = size;
260
261 struct ion_custom_data d;
262 switch (op) {
263 case CACHE_CLEAN:
264 d.cmd = ION_IOC_CLEAN_CACHES;
265 break;
266 case CACHE_INVALIDATE:
267 d.cmd = ION_IOC_INV_CACHES;
268 break;
269 case CACHE_CLEAN_AND_INVALIDATE:
270 default:
271 d.cmd = ION_IOC_CLEAN_INV_CACHES;
272 }
273
274 d.arg = (unsigned long)(&flush_data); // NOLINT
275 if (ioctl(ion_dev_fd_, INT(ION_IOC_CUSTOM), &d)) {
276 err = -errno;
277 ALOGE("%s: ION_IOC_CLEAN_INV_CACHES failed with error - %s", __FUNCTION__, strerror(errno));
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530278 return err;
279 }
280
Prabhanjan Kandula96e92342016-03-24 21:03:35 +0530281 return 0;
282}
283
Rohit Kulkarni3ac98392017-10-20 12:04:34 -0700284#else // This ion version is not supported
285
286int IonAlloc::OpenIonDevice() {
287 return -EINVAL;
288}
289
290void IonAlloc::CloseIonDevice() {
291}
292
293int IonAlloc::AllocBuffer(AllocData * /*data*/) {
294 return -EINVAL;
295}
296
297int IonAlloc::FreeBuffer(void * /*base*/, unsigned int /*size*/, unsigned int /*offset*/,
298 int /*fd*/, int /*ion_handle*/) {
299 return -EINVAL;
300}
301
302int IonAlloc::ImportBuffer(int /*fd*/) {
303 return -EINVAL;
304}
305
306int IonAlloc::CleanBuffer(void * /*base*/, unsigned int /*size*/, unsigned int /*offset*/,
307 int /*handle*/, int /*op*/, int /*fd*/) {
308 return -EINVAL;
309}
310
311#endif
312#endif // TARGET_ION_ABI_VERSION
313
314
315int IonAlloc::MapBuffer(void **base, unsigned int size, unsigned int offset, int fd) {
316 ATRACE_CALL();
317 int err = 0;
318 void *addr = 0;
319
320 addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
321 *base = addr;
322 if (addr == MAP_FAILED) {
323 err = -errno;
324 ALOGE("ion: Failed to map memory in the client: %s", strerror(errno));
325 } else {
326 ALOGD_IF(DEBUG, "ion: Mapped buffer base:%p size:%u offset:%u fd:%d", addr, size, offset, fd);
327 }
328
329 return err;
330}
331
332int IonAlloc::UnmapBuffer(void *base, unsigned int size, unsigned int /*offset*/) {
333 ATRACE_CALL();
334 ALOGD_IF(DEBUG, "ion: Unmapping buffer base:%p size:%u", base, size);
335
336 int err = 0;
337 if (munmap(base, size)) {
338 err = -errno;
339 ALOGE("ion: Failed to unmap memory at %p : %s", base, strerror(errno));
340 }
341
342 return err;
343}
344
Naseer Ahmede36f2242017-12-01 15:33:56 -0500345} // namespace gralloc