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