static int gralloc_map(gralloc_module_t const* module,
                       buffer_handle_t handle)
{
    private_handle_t* hnd = (private_handle_t*)handle;
    void *mappedAddress;
    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
        !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) {
        size_t size = hnd->size;
        IMemAlloc* memalloc = getAllocator(hnd->flags) ;
        int err = memalloc->map_buffer(&mappedAddress, size,
                                       hnd->offset, hnd->fd);
        if(err || mappedAddress == MAP_FAILED) {
            ALOGE("Could not mmap handle %p, fd=%d (%s)",
                  handle, hnd->fd, strerror(errno));
            hnd->base = 0;
            return -errno;
        }

        hnd->base = intptr_t(mappedAddress) + hnd->offset;
        mappedAddress = MAP_FAILED;
        size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
        err = memalloc->map_buffer(&mappedAddress, size,
                                       hnd->offset_metadata, hnd->fd_metadata);
        if(err || mappedAddress == MAP_FAILED) {
            ALOGE("Could not mmap handle %p, fd=%d (%s)",
                  handle, hnd->fd_metadata, strerror(errno));
            hnd->base_metadata = 0;
            return -errno;
        }
        hnd->base_metadata = intptr_t(mappedAddress) + hnd->offset_metadata;
    }
    return 0;
}
int PmemKernelController::allocate(alloc_data& data, int usage)
{
    int ret = 0;
    bool adspFallback = false;
    if (!(usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP))
        adspFallback = true;

    // Try SMI first
    if ((usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP) ||
        (usage & GRALLOC_USAGE_EXTERNAL_DISP)    ||
        (usage & GRALLOC_USAGE_PROTECTED))
    {
        int tempFd = open(DEVICE_PMEM_SMIPOOL, O_RDWR, 0);
        if(tempFd > 0) {
            close(tempFd);
            IMemAlloc* memalloc;
            memalloc = new PmemKernelAlloc(DEVICE_PMEM_SMIPOOL);
            ret = memalloc->alloc_buffer(data);
            if(ret >= 0)
                return ret;
            else {
                if(adspFallback)
                    ALOGW("Allocation from SMI failed, trying ADSP");
            }
        }
    }

    if ((usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) || adspFallback) {
        ret = mPmemAdspAlloc->alloc_buffer(data);
    }
    return ret;
}
static int gralloc_map(gralloc_module_t const* module,
                       buffer_handle_t handle,
                       void** vaddr)
{
    private_handle_t* hnd = (private_handle_t*)handle;
    void *mappedAddress;
    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
        !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) {
        size_t size = hnd->size;
        IMemAlloc* memalloc = getAllocator(hnd->flags) ;
        int err = memalloc->map_buffer(&mappedAddress, size,
                                       hnd->offset, hnd->fd);
        if(err) {
            ALOGE("Could not mmap handle %p, fd=%d (%s)",
                  handle, hnd->fd, strerror(errno));
            hnd->base = 0;
            return -errno;
        }

        if (mappedAddress == MAP_FAILED) {
            ALOGE("Could not mmap handle %p, fd=%d (%s)",
                  handle, hnd->fd, strerror(errno));
            hnd->base = 0;
            return -errno;
        }
        hnd->base = intptr_t(mappedAddress) + hnd->offset;
        //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
        //        hnd->fd, hnd->offset, hnd->size, mappedAddress);
    }
    *vaddr = (void*)hnd->base;
    return 0;
}
示例#4
0
int gpu_context_t::free_impl(private_handle_t const* hnd) {
    private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
    if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
        const size_t bufferSize = m->finfo.line_length * m->info.yres;
        int index = (hnd->base - m->framebuffer->base) / bufferSize;
        m->bufferMask &= ~(1<<index);
    } else {

        terminateBuffer(&m->base, const_cast<private_handle_t*>(hnd));
        IMemAlloc* memalloc = mAllocCtrl->getAllocator(hnd->flags);
        int err = memalloc->free_buffer((void*)hnd->base, (size_t) hnd->size,
                                        hnd->offset, hnd->fd);
        if(err)
            return err;
        // free the metadata space
        unsigned long size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
        err = memalloc->free_buffer((void*)hnd->base_metadata,
                                    (size_t) size, hnd->offset_metadata,
                                    hnd->fd_metadata);
        if (err)
            return err;
    }
    delete hnd;
    return 0;
}
示例#5
0
static int gralloc_unmap(gralloc_module_t const* module,
                         buffer_handle_t handle)
{
    if(!module)
        return -EINVAL;

    private_handle_t* hnd = (private_handle_t*)handle;
    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
        int err = -EINVAL;
        void* base = (void*)hnd->base;
        size_t size = hnd->size;
        IMemAlloc* memalloc = getAllocator(hnd->flags) ;
        if(memalloc != NULL) {
            err = memalloc->unmap_buffer(base, size, hnd->offset);
            if (err) {
                ALOGE("Could not unmap memory at address %p", base);
            }
            base = (void*)hnd->base_metadata;
            size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
            err = memalloc->unmap_buffer(base, size, hnd->offset_metadata);
            if (err) {
                ALOGE("Could not unmap memory at address %p", base);
            }
        }
    }
    /* need to initialize the pointer to NULL otherwise unmapping for that
     * buffer happens twice which leads to crash */
    hnd->base = 0;
    hnd->base_metadata = 0;
    return 0;
}
static int gralloc_unmap(gralloc_module_t const* module,
                         buffer_handle_t handle)
{
    private_handle_t* hnd = (private_handle_t*)handle;
    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
        int err = -EINVAL;
        void* base = (void*)hnd->base;
        size_t size = hnd->size;
        IMemAlloc* memalloc = getAllocator(hnd->flags) ;
        if(memalloc != NULL) {
            err = memalloc->unmap_buffer(base, size, hnd->offset);
            if (err) {
                ALOGE("Could not unmap memory at address %p", base);
            }
            base = (void*)hnd->base_metadata;
            size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
            err = memalloc->unmap_buffer(base, size, hnd->offset_metadata);
            if (err) {
                ALOGE("Could not unmap memory at address %p", base);
            }
        }
    }
    hnd->base = 0;
    return 0;
}
int gralloc_unlock(gralloc_module_t const* module,
                   buffer_handle_t handle)
{
    if (private_handle_t::validate(handle) < 0)
        return -EINVAL;

    private_handle_t* hnd = (private_handle_t*)handle;

    if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
        int err;
        IMemAlloc* memalloc = getAllocator(hnd->flags) ;
        err = memalloc->clean_buffer((void*)hnd->base,
                                     hnd->size, hnd->offset, hnd->fd);
        ALOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%x, flags = 0x%x) err=%s\n",
                 hnd, hnd->offset, hnd->size, hnd->flags, strerror(errno));
        unsigned long size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
        err = memalloc->clean_buffer((void*)hnd->base_metadata, size,
                hnd->offset_metadata, hnd->fd_metadata);
        ALOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%lu, "
                "flags = 0x%x) err=%s\n", hnd, hnd->offset_metadata, size,
                hnd->flags, strerror(errno));
        hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
    }

    if ((hnd->flags & private_handle_t::PRIV_FLAGS_SW_LOCK)) {
        // Unlock the buffer.
        if (GENLOCK_NO_ERROR != genlock_unlock_buffer((native_handle_t *)handle)) {
            ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
            return -EINVAL;
        } else
            hnd->flags &= ~private_handle_t::PRIV_FLAGS_SW_LOCK;
    }
    return 0;
}
static int gralloc_map_and_invalidate (gralloc_module_t const* module,
                                       buffer_handle_t handle, int usage,
                                       int l, int t, int w, int h)
{
    if (private_handle_t::validate(handle) < 0)
        return -EINVAL;

    int err = 0;
    private_handle_t* hnd = (private_handle_t*)handle;
    if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
        if (hnd->base == 0) {
            // we need to map for real
            pthread_mutex_t* const lock = &sMapLock;
            pthread_mutex_lock(lock);
            err = gralloc_map(module, handle);
            pthread_mutex_unlock(lock);
        }
        //Invalidate if reading in software. No need to do this for the metadata
        //buffer as it is only read/written in software.
        IMemAlloc* memalloc = getAllocator(hnd->flags) ;
        err = memalloc->clean_buffer((void*)hnd->base,
                                     hnd->size, hnd->offset, hnd->fd,
                                     CACHE_INVALIDATE);
        if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) &&
            !(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
            // Mark the buffer to be flushed after cpu read/write
            hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
        }
    } else {
        hnd->flags |= private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
    }
    return err;
}
示例#9
0
int gralloc_unlock(gralloc_module_t const* module,
                   buffer_handle_t handle)
{
    if (!module || private_handle_t::validate(handle) < 0)
        return -EINVAL;

    int err = 0;
    private_handle_t* hnd = (private_handle_t*)handle;

    if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
        IMemAlloc* memalloc = getAllocator(hnd->flags);
        if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
            err = memalloc->clean_buffer((void*)hnd->base,
                                         hnd->size, hnd->offset, hnd->fd,
                                         CACHE_CLEAN_AND_INVALIDATE);
            hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
        } else if(hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH) {
            hnd->flags &= ~private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
        } else {
            //Probably a round about way to do this, but this avoids adding new
            //flags
            err = memalloc->clean_buffer((void*)hnd->base,
                                         hnd->size, hnd->offset, hnd->fd,
                                         CACHE_INVALIDATE);
        }
    }

    return err;
}
int gpu_context_t::free_impl(private_handle_t const* hnd) {
    private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
    if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
        // free this buffer
        const size_t bufferSize = m->finfo.line_length * m->info.yres;
        int index = (hnd->base - m->framebuffer->base) / bufferSize;
        m->bufferMask &= ~(1<<index);
    } else {
        terminateBuffer(&m->base, const_cast<private_handle_t*>(hnd));
        IMemAlloc* memalloc = mAllocCtrl->getAllocator(hnd->flags);
        int err = memalloc->free_buffer((void*)hnd->base, (size_t) hnd->size,
                                        hnd->offset, hnd->fd);
        if(err)
            return err;
    }

    // Release the genlock
    int err = genlock_release_lock((native_handle_t*)hnd);
    if (err) {
        ALOGE("%s: genlock_release_lock failed", __FUNCTION__);
    }

    delete hnd;
    return 0;
}
static int gralloc_map_and_invalidate (gralloc_module_t const* module,
                                       buffer_handle_t handle, int usage,
                                       int l, int t, int w, int h)
{
    if (private_handle_t::validate(handle) < 0)
        return -EINVAL;

    int err = 0;
    private_handle_t* hnd = (private_handle_t*)handle;
    if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
        if (hnd->base == 0) {
            // we need to map for real
            pthread_mutex_t* const lock = &sMapLock;
            pthread_mutex_lock(lock);
            err = gralloc_map(module, handle);
            pthread_mutex_unlock(lock);
        }
#ifdef QCOM_BSP_WITH_GENLOCK
        // Lock the buffer for read/write operation as specified. Write lock
        // has a higher priority over read lock.
        int lockType = 0;
        if (usage & GRALLOC_USAGE_SW_WRITE_MASK) {
            lockType = GENLOCK_WRITE_LOCK;
        } else if (usage & GRALLOC_USAGE_SW_READ_MASK) {
            lockType = GENLOCK_READ_LOCK;
        }

        int timeout = GENLOCK_MAX_TIMEOUT;
        if (GENLOCK_NO_ERROR != genlock_lock_buffer((native_handle_t *)handle,
                                                    (genlock_lock_type)lockType,
                                                    timeout)) {
            ALOGE("%s: genlock_lock_buffer (lockType=0x%x) failed", __FUNCTION__,
                  lockType);
            return -EINVAL;
        } else {
            // Mark this buffer as locked for SW read/write operation.
            hnd->flags |= private_handle_t::PRIV_FLAGS_SW_LOCK;
        }
#endif
         if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
            //Invalidate if reading in software. No need to do this for the
            //metadata buffer as it is only read/written in software.
            IMemAlloc* memalloc = getAllocator(hnd->flags) ;
            err = memalloc->clean_buffer((void*)hnd->base,
                                         hnd->size, hnd->offset, hnd->fd,
                                         CACHE_INVALIDATE);
            if (usage & GRALLOC_USAGE_SW_WRITE_MASK) {
                // Mark the buffer to be flushed after cpu read/write
                hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
            }
        }
     } else {
        hnd->flags |= private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
    }
    return err;
}
void free_buffer(private_handle_t *hnd)
{
    gralloc::IAllocController* sAlloc =
        gralloc::IAllocController::getInstance();
    if (hnd && hnd->fd > 0) {
        IMemAlloc* memalloc = sAlloc->getAllocator(hnd->flags);
        memalloc->free_buffer((void*)hnd->base, hnd->size, hnd->offset, hnd->fd);
    }
    if(hnd)
        delete hnd;

}
示例#13
0
static int gralloc_map(gralloc_module_t const* module,
                       buffer_handle_t handle)
{
    ATRACE_CALL();
    if(!module)
        return -EINVAL;

    private_handle_t* hnd = (private_handle_t*)handle;
    unsigned int size = 0;
    int err = 0;
    IMemAlloc* memalloc = getAllocator(hnd->flags) ;
    void *mappedAddress;
    // Dont map FRAMEBUFFER and SECURE_BUFFERS
    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
        !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) {
        size = hnd->size;
        err = memalloc->map_buffer(&mappedAddress, size,
                                       hnd->offset, hnd->fd);
        if(err || mappedAddress == MAP_FAILED) {
            ALOGE("Could not mmap handle %p, fd=%d (%s)",
                  handle, hnd->fd, strerror(errno));
            hnd->base = 0;
            return -errno;
        }

        hnd->base = uint64_t(mappedAddress) + hnd->offset;
    }

    //Allow mapping of metadata for all buffers and SECURE_BUFFER
    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
        mappedAddress = MAP_FAILED;
        size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
        err = memalloc->map_buffer(&mappedAddress, size,
                                       hnd->offset_metadata, hnd->fd_metadata);
        if(err || mappedAddress == MAP_FAILED) {
            ALOGE("Could not mmap handle %p, fd=%d (%s)",
                  handle, hnd->fd_metadata, strerror(errno));
            hnd->base_metadata = 0;
            return -errno;
        }
        hnd->base_metadata = uint64_t(mappedAddress) + hnd->offset_metadata;
    }
    return 0;
}
示例#14
0
static int gralloc_map(gralloc_module_t const* module,
                       buffer_handle_t handle)
{
    ATRACE_CALL();
    if(!module)
        return -EINVAL;

    private_handle_t* hnd = (private_handle_t*)handle;
    unsigned int size = 0;
    int err = 0;
    IMemAlloc* memalloc = getAllocator(hnd->flags) ;
    void *mappedAddress = MAP_FAILED;
    hnd->base = 0;

    // Dont map framebuffer and secure buffers
    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
        !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) {
        size = hnd->size;
        err = memalloc->map_buffer(&mappedAddress, size,
                                       hnd->offset, hnd->fd);
        if(err || mappedAddress == MAP_FAILED) {
            ALOGE("Could not mmap handle %p, fd=%d (%s)",
                  handle, hnd->fd, strerror(errno));
            return -errno;
        }

        hnd->base = uint64_t(mappedAddress);
    } else {
        // Cannot map secure buffers or framebuffers, but still need to map
        // metadata for secure buffers.
        // If mapping a secure buffers fails, the framework needs to get
        // an error code.
        err = -EACCES;
    }

    //Allow mapping of metadata for all buffers including secure ones, but not
    //of framebuffer
    int metadata_err = gralloc_map_metadata(handle);
    if(!err) {
        err = metadata_err;
    }
    return err;
}
示例#15
0
int gralloc_unlock(gralloc_module_t const* module,
                   buffer_handle_t handle)
{
    ATRACE_CALL();
    if (!module || private_handle_t::validate(handle) < 0)
        return -EINVAL;

    int err = 0;
    private_handle_t* hnd = (private_handle_t*)handle;

    IMemAlloc* memalloc = getAllocator(hnd->flags);
    if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
        err = memalloc->clean_buffer((void*)hnd->base,
                hnd->size, hnd->offset, hnd->fd,
                CACHE_CLEAN);
        hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
    }

    return err;
}
示例#16
0
static int gralloc_map_metadata(buffer_handle_t handle) {
    private_handle_t* hnd = (private_handle_t*)handle;
    hnd->base_metadata = 0;
    IMemAlloc* memalloc = getAllocator(hnd->flags) ;
    void *mappedAddress = MAP_FAILED;
    unsigned int size = 0;
    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
        mappedAddress = MAP_FAILED;
        size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
        int ret = memalloc->map_buffer(&mappedAddress, size,
                                       hnd->offset_metadata, hnd->fd_metadata);
        if(ret || mappedAddress == MAP_FAILED) {
            ALOGE("Could not mmap metadata for handle %p, fd=%d (%s)",
                  hnd, hnd->fd_metadata, strerror(errno));
            return -errno;
        }
        hnd->base_metadata = uint64_t(mappedAddress);
    }
    return 0;
}
示例#17
0
static int gralloc_map_and_invalidate (gralloc_module_t const* module,
                                       buffer_handle_t handle, int usage)
{
    ATRACE_CALL();
    if (!module || private_handle_t::validate(handle) < 0)
        return -EINVAL;

    int err = 0;
    private_handle_t* hnd = (private_handle_t*)handle;
    if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
        if (hnd->base == 0) {
            // we need to map for real
            pthread_mutex_t* const lock = &sMapLock;
            pthread_mutex_lock(lock);
            err = gralloc_map(module, handle);
            pthread_mutex_unlock(lock);
        }
        if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION and
                hnd->flags & private_handle_t::PRIV_FLAGS_CACHED) {
            //Invalidate if CPU reads in software and there are non-CPU
            //writers. No need to do this for the metadata buffer as it is
            //only read/written in software.
            if ((usage & GRALLOC_USAGE_SW_READ_MASK) and
                    (hnd->flags & private_handle_t::PRIV_FLAGS_NON_CPU_WRITER))
            {
                IMemAlloc* memalloc = getAllocator(hnd->flags) ;
                err = memalloc->clean_buffer((void*)hnd->base,
                        hnd->size, hnd->offset, hnd->fd,
                        CACHE_INVALIDATE);
            }
            //Mark the buffer to be flushed after CPU write.
            if (usage & GRALLOC_USAGE_SW_WRITE_MASK) {
                hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
            }
        }
    }

    return err;
}
int gralloc_unlock(gralloc_module_t const* module,
                   buffer_handle_t handle)
{
    if (private_handle_t::validate(handle) < 0)
        return -EINVAL;
    int err = 0;
    private_handle_t* hnd = (private_handle_t*)handle;
    IMemAlloc* memalloc = getAllocator(hnd->flags);

    if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
        err = memalloc->clean_buffer((void*)hnd->base,
                                     hnd->size, hnd->offset, hnd->fd,
                                     CACHE_CLEAN_AND_INVALIDATE);
        hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
    } else if(hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH) {
        hnd->flags &= ~private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
    } else {
        //Probably a round about way to do this, but this avoids adding new
        //flags
        err = memalloc->clean_buffer((void*)hnd->base,
                                     hnd->size, hnd->offset, hnd->fd,
                                     CACHE_INVALIDATE);
    }

#ifndef QCOM_BSP
    if ((hnd->flags & private_handle_t::PRIV_FLAGS_SW_LOCK)) {
        // Unlock the buffer.
        if (GENLOCK_NO_ERROR != genlock_unlock_buffer((native_handle_t *)handle)) {
            ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
            return -EINVAL;
        } else
            hnd->flags &= ~private_handle_t::PRIV_FLAGS_SW_LOCK;
    }
#endif

    return err;
}
示例#19
0
static int gralloc_unmap(gralloc_module_t const* module,
                         buffer_handle_t handle)
{
    ATRACE_CALL();
    int err = -EINVAL;
    if(!module)
        return err;

    private_handle_t* hnd = (private_handle_t*)handle;
    IMemAlloc* memalloc = getAllocator(hnd->flags) ;
    if(!memalloc)
        return err;

    if(hnd->base) {
        err = memalloc->unmap_buffer((void*)hnd->base, hnd->size, hnd->offset);
        if (err) {
            ALOGE("Could not unmap memory at address %p, %s", (void*) hnd->base,
                    strerror(errno));
            return -errno;
        }
        hnd->base = 0;
    }

    if(hnd->base_metadata) {
        unsigned int size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
        err = memalloc->unmap_buffer((void*)hnd->base_metadata,
                size, hnd->offset_metadata);
        if (err) {
            ALOGE("Could not unmap memory at address %p, %s",
                    (void*) hnd->base_metadata, strerror(errno));
            return -errno;
        }
        hnd->base_metadata = 0;
    }

    return 0;
}