Path: blob/21.2-virgl/src/freedreno/drm/msm_bo.c
4564 views
/*1* Copyright (C) 2012-2018 Rob Clark <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,19* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE20* SOFTWARE.21*22* Authors:23* Rob Clark <[email protected]>24*/2526#include "msm_priv.h"2728static int29bo_allocate(struct msm_bo *msm_bo)30{31struct fd_bo *bo = &msm_bo->base;32if (!msm_bo->offset) {33struct drm_msm_gem_info req = {34.handle = bo->handle,35.info = MSM_INFO_GET_OFFSET,36};37int ret;3839/* if the buffer is already backed by pages then this40* doesn't actually do anything (other than giving us41* the offset)42*/43ret =44drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));45if (ret) {46ERROR_MSG("alloc failed: %s", strerror(errno));47return ret;48}4950msm_bo->offset = req.value;51}5253return 0;54}5556static int57msm_bo_offset(struct fd_bo *bo, uint64_t *offset)58{59struct msm_bo *msm_bo = to_msm_bo(bo);60int ret = bo_allocate(msm_bo);61if (ret)62return ret;63*offset = msm_bo->offset;64return 0;65}6667static int68msm_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op)69{70struct drm_msm_gem_cpu_prep req = {71.handle = bo->handle,72.op = op,73};7475get_abs_timeout(&req.timeout, 5000000000);7677return drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_CPU_PREP, &req, sizeof(req));78}7980static void81msm_bo_cpu_fini(struct fd_bo *bo)82{83struct drm_msm_gem_cpu_fini req = {84.handle = bo->handle,85};8687drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_CPU_FINI, &req, sizeof(req));88}8990static int91msm_bo_madvise(struct fd_bo *bo, int willneed)92{93struct drm_msm_gem_madvise req = {94.handle = bo->handle,95.madv = willneed ? MSM_MADV_WILLNEED : MSM_MADV_DONTNEED,96};97int ret;9899/* older kernels do not support this: */100if (bo->dev->version < FD_VERSION_MADVISE)101return willneed;102103ret =104drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_MADVISE, &req, sizeof(req));105if (ret)106return ret;107108return req.retained;109}110111static uint64_t112msm_bo_iova(struct fd_bo *bo)113{114struct drm_msm_gem_info req = {115.handle = bo->handle,116.info = MSM_INFO_GET_IOVA,117};118int ret;119120ret = drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));121if (ret)122return 0;123124return req.value;125}126127static void128msm_bo_set_name(struct fd_bo *bo, const char *fmt, va_list ap)129{130struct drm_msm_gem_info req = {131.handle = bo->handle,132.info = MSM_INFO_SET_NAME,133};134char buf[32];135int sz;136137if (bo->dev->version < FD_VERSION_SOFTPIN)138return;139140sz = vsnprintf(buf, sizeof(buf), fmt, ap);141142req.value = VOID2U64(buf);143req.len = MIN2(sz, sizeof(buf));144145drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));146}147148static void149msm_bo_destroy(struct fd_bo *bo)150{151struct msm_bo *msm_bo = to_msm_bo(bo);152free(msm_bo);153}154155static const struct fd_bo_funcs funcs = {156.offset = msm_bo_offset,157.cpu_prep = msm_bo_cpu_prep,158.cpu_fini = msm_bo_cpu_fini,159.madvise = msm_bo_madvise,160.iova = msm_bo_iova,161.set_name = msm_bo_set_name,162.destroy = msm_bo_destroy,163};164165/* allocate a buffer handle: */166int167msm_bo_new_handle(struct fd_device *dev, uint32_t size, uint32_t flags,168uint32_t *handle)169{170struct drm_msm_gem_new req = {171.size = size,172.flags = MSM_BO_WC, // TODO figure out proper flags..173};174int ret;175176if (flags & FD_BO_SCANOUT)177req.flags |= MSM_BO_SCANOUT;178179if (flags & FD_BO_GPUREADONLY)180req.flags |= MSM_BO_GPU_READONLY;181182ret = drmCommandWriteRead(dev->fd, DRM_MSM_GEM_NEW, &req, sizeof(req));183if (ret)184return ret;185186*handle = req.handle;187188return 0;189}190191/* allocate a new buffer object */192struct fd_bo *193msm_bo_from_handle(struct fd_device *dev, uint32_t size, uint32_t handle)194{195struct msm_bo *msm_bo;196struct fd_bo *bo;197198msm_bo = calloc(1, sizeof(*msm_bo));199if (!msm_bo)200return NULL;201202bo = &msm_bo->base;203bo->funcs = &funcs;204205return bo;206}207208209