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