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