17e102996Smaya/*
27e102996Smaya * Copyright (C) 2012-2018 Rob Clark <robclark@freedesktop.org>
37e102996Smaya *
47e102996Smaya * Permission is hereby granted, free of charge, to any person obtaining a
57e102996Smaya * copy of this software and associated documentation files (the "Software"),
67e102996Smaya * to deal in the Software without restriction, including without limitation
77e102996Smaya * the rights to use, copy, modify, merge, publish, distribute, sublicense,
87e102996Smaya * and/or sell copies of the Software, and to permit persons to whom the
97e102996Smaya * Software is furnished to do so, subject to the following conditions:
107e102996Smaya *
117e102996Smaya * The above copyright notice and this permission notice (including the next
127e102996Smaya * paragraph) shall be included in all copies or substantial portions of the
137e102996Smaya * Software.
147e102996Smaya *
157e102996Smaya * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167e102996Smaya * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177e102996Smaya * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
187e102996Smaya * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
197e102996Smaya * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
207e102996Smaya * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
217e102996Smaya * SOFTWARE.
227e102996Smaya *
237e102996Smaya * Authors:
247e102996Smaya *    Rob Clark <robclark@freedesktop.org>
257e102996Smaya */
267e102996Smaya
277e102996Smaya#include "msm_priv.h"
287e102996Smaya
297ec681f3Smrgstatic int
307ec681f3Smrgbo_allocate(struct msm_bo *msm_bo)
317e102996Smaya{
327ec681f3Smrg   struct fd_bo *bo = &msm_bo->base;
337ec681f3Smrg   if (!msm_bo->offset) {
347ec681f3Smrg      struct drm_msm_gem_info req = {
357ec681f3Smrg         .handle = bo->handle,
367ec681f3Smrg         .info = MSM_INFO_GET_OFFSET,
377ec681f3Smrg      };
387ec681f3Smrg      int ret;
397ec681f3Smrg
407ec681f3Smrg      /* if the buffer is already backed by pages then this
417ec681f3Smrg       * doesn't actually do anything (other than giving us
427ec681f3Smrg       * the offset)
437ec681f3Smrg       */
447ec681f3Smrg      ret =
457ec681f3Smrg         drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));
467ec681f3Smrg      if (ret) {
477ec681f3Smrg         ERROR_MSG("alloc failed: %s", strerror(errno));
487ec681f3Smrg         return ret;
497ec681f3Smrg      }
507ec681f3Smrg
517ec681f3Smrg      msm_bo->offset = req.value;
527ec681f3Smrg   }
537ec681f3Smrg
547ec681f3Smrg   return 0;
557e102996Smaya}
567e102996Smaya
577ec681f3Smrgstatic int
587ec681f3Smrgmsm_bo_offset(struct fd_bo *bo, uint64_t *offset)
597e102996Smaya{
607ec681f3Smrg   struct msm_bo *msm_bo = to_msm_bo(bo);
617ec681f3Smrg   int ret = bo_allocate(msm_bo);
627ec681f3Smrg   if (ret)
637ec681f3Smrg      return ret;
647ec681f3Smrg   *offset = msm_bo->offset;
657ec681f3Smrg   return 0;
667e102996Smaya}
677e102996Smaya
687ec681f3Smrgstatic int
697ec681f3Smrgmsm_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op)
707e102996Smaya{
717ec681f3Smrg   struct drm_msm_gem_cpu_prep req = {
727ec681f3Smrg      .handle = bo->handle,
737ec681f3Smrg      .op = op,
747ec681f3Smrg   };
757e102996Smaya
767ec681f3Smrg   get_abs_timeout(&req.timeout, 5000000000);
777e102996Smaya
787ec681f3Smrg   return drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_CPU_PREP, &req, sizeof(req));
797e102996Smaya}
807e102996Smaya
817ec681f3Smrgstatic void
827ec681f3Smrgmsm_bo_cpu_fini(struct fd_bo *bo)
837e102996Smaya{
847ec681f3Smrg   struct drm_msm_gem_cpu_fini req = {
857ec681f3Smrg      .handle = bo->handle,
867ec681f3Smrg   };
877e102996Smaya
887ec681f3Smrg   drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_CPU_FINI, &req, sizeof(req));
897e102996Smaya}
907e102996Smaya
917ec681f3Smrgstatic int
927ec681f3Smrgmsm_bo_madvise(struct fd_bo *bo, int willneed)
937e102996Smaya{
947ec681f3Smrg   struct drm_msm_gem_madvise req = {
957ec681f3Smrg      .handle = bo->handle,
967ec681f3Smrg      .madv = willneed ? MSM_MADV_WILLNEED : MSM_MADV_DONTNEED,
977ec681f3Smrg   };
987ec681f3Smrg   int ret;
997ec681f3Smrg
1007ec681f3Smrg   /* older kernels do not support this: */
1017ec681f3Smrg   if (bo->dev->version < FD_VERSION_MADVISE)
1027ec681f3Smrg      return willneed;
1037ec681f3Smrg
1047ec681f3Smrg   ret =
1057ec681f3Smrg      drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_MADVISE, &req, sizeof(req));
1067ec681f3Smrg   if (ret)
1077ec681f3Smrg      return ret;
1087ec681f3Smrg
1097ec681f3Smrg   return req.retained;
1107e102996Smaya}
1117e102996Smaya
1127ec681f3Smrgstatic uint64_t
1137ec681f3Smrgmsm_bo_iova(struct fd_bo *bo)
1147e102996Smaya{
1157ec681f3Smrg   struct drm_msm_gem_info req = {
1167ec681f3Smrg      .handle = bo->handle,
1177ec681f3Smrg      .info = MSM_INFO_GET_IOVA,
1187ec681f3Smrg   };
1197ec681f3Smrg   int ret;
1207e102996Smaya
1217ec681f3Smrg   ret = drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));
1227ec681f3Smrg   if (ret)
1237ec681f3Smrg      return 0;
1247e102996Smaya
1257ec681f3Smrg   return req.value;
1267e102996Smaya}
1277e102996Smaya
1287ec681f3Smrgstatic void
1297ec681f3Smrgmsm_bo_set_name(struct fd_bo *bo, const char *fmt, va_list ap)
1307e102996Smaya{
1317ec681f3Smrg   struct drm_msm_gem_info req = {
1327ec681f3Smrg      .handle = bo->handle,
1337ec681f3Smrg      .info = MSM_INFO_SET_NAME,
1347ec681f3Smrg   };
1357ec681f3Smrg   char buf[32];
1367ec681f3Smrg   int sz;
1377e102996Smaya
1387ec681f3Smrg   if (bo->dev->version < FD_VERSION_SOFTPIN)
1397ec681f3Smrg      return;
1407e102996Smaya
1417ec681f3Smrg   sz = vsnprintf(buf, sizeof(buf), fmt, ap);
1427e102996Smaya
1437ec681f3Smrg   req.value = VOID2U64(buf);
1447ec681f3Smrg   req.len = MIN2(sz, sizeof(buf));
1457e102996Smaya
1467ec681f3Smrg   drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));
1477e102996Smaya}
1487e102996Smaya
1497ec681f3Smrgstatic void
1507ec681f3Smrgmsm_bo_destroy(struct fd_bo *bo)
1517e102996Smaya{
1527ec681f3Smrg   struct msm_bo *msm_bo = to_msm_bo(bo);
1537ec681f3Smrg   free(msm_bo);
1547e102996Smaya}
1557e102996Smaya
1567e102996Smayastatic const struct fd_bo_funcs funcs = {
1577ec681f3Smrg   .offset = msm_bo_offset,
1587ec681f3Smrg   .cpu_prep = msm_bo_cpu_prep,
1597ec681f3Smrg   .cpu_fini = msm_bo_cpu_fini,
1607ec681f3Smrg   .madvise = msm_bo_madvise,
1617ec681f3Smrg   .iova = msm_bo_iova,
1627ec681f3Smrg   .set_name = msm_bo_set_name,
1637ec681f3Smrg   .destroy = msm_bo_destroy,
1647e102996Smaya};
1657e102996Smaya
1667e102996Smaya/* allocate a buffer handle: */
1677ec681f3Smrgint
1687ec681f3Smrgmsm_bo_new_handle(struct fd_device *dev, uint32_t size, uint32_t flags,
1697ec681f3Smrg                  uint32_t *handle)
1707e102996Smaya{
1717ec681f3Smrg   struct drm_msm_gem_new req = {
1727ec681f3Smrg      .size = size,
1737ec681f3Smrg   };
1747ec681f3Smrg   int ret;
1757ec681f3Smrg
1767ec681f3Smrg   if (flags & FD_BO_SCANOUT)
1777ec681f3Smrg      req.flags |= MSM_BO_SCANOUT;
1787e102996Smaya
1797ec681f3Smrg   if (flags & FD_BO_GPUREADONLY)
1807ec681f3Smrg      req.flags |= MSM_BO_GPU_READONLY;
1817e102996Smaya
1827ec681f3Smrg   if (flags & FD_BO_CACHED_COHERENT)
1837ec681f3Smrg      req.flags |= MSM_BO_CACHED_COHERENT;
1847ec681f3Smrg   else
1857ec681f3Smrg      req.flags |= MSM_BO_WC;
1867e102996Smaya
1877ec681f3Smrg   ret = drmCommandWriteRead(dev->fd, DRM_MSM_GEM_NEW, &req, sizeof(req));
1887ec681f3Smrg   if (ret)
1897ec681f3Smrg      return ret;
1907e102996Smaya
1917ec681f3Smrg   *handle = req.handle;
1927e102996Smaya
1937ec681f3Smrg   return 0;
1947e102996Smaya}
1957e102996Smaya
1967e102996Smaya/* allocate a new buffer object */
1977ec681f3Smrgstruct fd_bo *
1987ec681f3Smrgmsm_bo_from_handle(struct fd_device *dev, uint32_t size, uint32_t handle)
1997e102996Smaya{
2007ec681f3Smrg   struct msm_bo *msm_bo;
2017ec681f3Smrg   struct fd_bo *bo;
2027e102996Smaya
2037ec681f3Smrg   msm_bo = calloc(1, sizeof(*msm_bo));
2047ec681f3Smrg   if (!msm_bo)
2057ec681f3Smrg      return NULL;
2067e102996Smaya
2077ec681f3Smrg   bo = &msm_bo->base;
2087ec681f3Smrg   bo->funcs = &funcs;
2097e102996Smaya
2107ec681f3Smrg   return bo;
2117e102996Smaya}
212