Home | History | Annotate | Download | only in libgralloc1
      1 /*
      2  * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
      3 
      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>
     34 #include <stdlib.h>
     35 #include <fcntl.h>
     36 #include <cutils/log.h>
     37 #include <errno.h>
     38 #include <utils/Trace.h>
     39 #include <string.h>
     40 
     41 #include "gralloc_priv.h"
     42 #include "gr_utils.h"
     43 #include "gr_ion_alloc.h"
     44 
     45 namespace gralloc1 {
     46 
     47 bool IonAlloc::Init() {
     48   if (ion_dev_fd_ == FD_INIT) {
     49     ion_dev_fd_ = open(kIonDevice, O_RDONLY);
     50   }
     51 
     52   if (ion_dev_fd_ < 0) {
     53     ALOGE("%s: Failed to open ion device - %s", __FUNCTION__, strerror(errno));
     54     ion_dev_fd_ = FD_INIT;
     55     return false;
     56   }
     57 
     58   return true;
     59 }
     60 
     61 void IonAlloc::CloseIonDevice() {
     62   if (ion_dev_fd_ > FD_INIT) {
     63     close(ion_dev_fd_);
     64   }
     65 
     66   ion_dev_fd_ = FD_INIT;
     67 }
     68 
     69 int IonAlloc::AllocBuffer(AllocData *data) {
     70   ATRACE_CALL();
     71   int err = 0;
     72   struct ion_handle_data handle_data;
     73   struct ion_fd_data fd_data;
     74   struct ion_allocation_data ion_alloc_data;
     75 
     76   ion_alloc_data.len = data->size;
     77   ion_alloc_data.align = data->align;
     78   ion_alloc_data.heap_id_mask = data->heap_id;
     79   ion_alloc_data.flags = data->flags;
     80   ion_alloc_data.flags |= data->uncached ? 0 : ION_FLAG_CACHED;
     81 
     82   if (ioctl(ion_dev_fd_, INT(ION_IOC_ALLOC), &ion_alloc_data)) {
     83     err = -errno;
     84     ALOGE("ION_IOC_ALLOC failed with error - %s", strerror(errno));
     85     return err;
     86   }
     87 
     88   fd_data.handle = ion_alloc_data.handle;
     89   handle_data.handle = ion_alloc_data.handle;
     90   if (ioctl(ion_dev_fd_, INT(ION_IOC_MAP), &fd_data)) {
     91     err = -errno;
     92     ALOGE("%s: ION_IOC_MAP failed with error - %s", __FUNCTION__, strerror(errno));
     93     ioctl(ion_dev_fd_, INT(ION_IOC_FREE), &handle_data);
     94     return err;
     95   }
     96 
     97   data->fd = fd_data.fd;
     98   data->ion_handle = handle_data.handle;
     99   ALOGD_IF(DEBUG, "ion: Allocated buffer size:%zu fd:%d handle:0x%x",
    100           ion_alloc_data.len, data->fd, data->ion_handle);
    101 
    102   return 0;
    103 }
    104 
    105 int IonAlloc::FreeBuffer(void *base, unsigned int size, unsigned int offset, int fd,
    106                          int ion_handle) {
    107   ATRACE_CALL();
    108   int err = 0;
    109   ALOGD_IF(DEBUG, "ion: Freeing buffer base:%p size:%u fd:%d handle:0x%x", base, size, fd,
    110            ion_handle);
    111 
    112   if (base) {
    113     err = UnmapBuffer(base, size, offset);
    114   }
    115 
    116   if (ion_handle > 0) {
    117     struct ion_handle_data handle_data;
    118     handle_data.handle = ion_handle;
    119     ioctl(ion_dev_fd_, INT(ION_IOC_FREE), &handle_data);
    120   }
    121   close(fd);
    122   return err;
    123 }
    124 
    125 int IonAlloc::MapBuffer(void **base, unsigned int size, unsigned int offset, int fd) {
    126   ATRACE_CALL();
    127   int err = 0;
    128   void *addr = 0;
    129 
    130   // It is a (quirky) requirement of ION to have opened the
    131   // ion fd in the process that is doing the mapping
    132   addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    133   *base = addr;
    134   if (addr == MAP_FAILED) {
    135     err = -errno;
    136     ALOGE("ion: Failed to map memory in the client: %s", strerror(errno));
    137   } else {
    138     ALOGD_IF(DEBUG, "ion: Mapped buffer base:%p size:%u offset:%u fd:%d", addr, size, offset, fd);
    139   }
    140 
    141   return err;
    142 }
    143 
    144 int IonAlloc::ImportBuffer(int fd) {
    145   struct ion_fd_data fd_data;
    146   int err = 0;
    147   fd_data.fd = fd;
    148   if (ioctl(ion_dev_fd_, INT(ION_IOC_IMPORT), &fd_data)) {
    149     err = -errno;
    150     ALOGE("%s: ION_IOC_IMPORT failed with error - %s", __FUNCTION__, strerror(errno));
    151     return err;
    152   }
    153   return fd_data.handle;
    154 }
    155 
    156 int IonAlloc::UnmapBuffer(void *base, unsigned int size, unsigned int /*offset*/) {
    157   ATRACE_CALL();
    158   ALOGD_IF(DEBUG, "ion: Unmapping buffer  base:%p size:%u", base, size);
    159 
    160   int err = 0;
    161   if (munmap(base, size)) {
    162     err = -errno;
    163     ALOGE("ion: Failed to unmap memory at %p : %s", base, strerror(errno));
    164   }
    165 
    166   return err;
    167 }
    168 
    169 int IonAlloc::CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op) {
    170   ATRACE_CALL();
    171   ATRACE_INT("operation id", op);
    172   struct ion_flush_data flush_data;
    173   int err = 0;
    174 
    175   flush_data.handle = handle;
    176   flush_data.vaddr = base;
    177   // offset and length are unsigned int
    178   flush_data.offset = offset;
    179   flush_data.length = size;
    180 
    181   struct ion_custom_data d;
    182   switch (op) {
    183     case CACHE_CLEAN:
    184       d.cmd = ION_IOC_CLEAN_CACHES;
    185       break;
    186     case CACHE_INVALIDATE:
    187       d.cmd = ION_IOC_INV_CACHES;
    188       break;
    189     case CACHE_CLEAN_AND_INVALIDATE:
    190     default:
    191       d.cmd = ION_IOC_CLEAN_INV_CACHES;
    192   }
    193 
    194   d.arg = (unsigned long)(&flush_data);  // NOLINT
    195   if (ioctl(ion_dev_fd_, INT(ION_IOC_CUSTOM), &d)) {
    196     err = -errno;
    197     ALOGE("%s: ION_IOC_CLEAN_INV_CACHES failed with error - %s", __FUNCTION__, strerror(errno));
    198     return err;
    199   }
    200 
    201   return 0;
    202 }
    203 
    204 }  // namespace gralloc1
    205