1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2012-2018 Rob Clark <robclark@freedesktop.org> 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Rob Clark <robclark@freedesktop.org> 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "msm_priv.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_cistatic int 30bf215546Sopenharmony_cibo_allocate(struct msm_bo *msm_bo) 31bf215546Sopenharmony_ci{ 32bf215546Sopenharmony_ci struct fd_bo *bo = &msm_bo->base; 33bf215546Sopenharmony_ci if (!msm_bo->offset) { 34bf215546Sopenharmony_ci struct drm_msm_gem_info req = { 35bf215546Sopenharmony_ci .handle = bo->handle, 36bf215546Sopenharmony_ci .info = MSM_INFO_GET_OFFSET, 37bf215546Sopenharmony_ci }; 38bf215546Sopenharmony_ci int ret; 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci /* if the buffer is already backed by pages then this 41bf215546Sopenharmony_ci * doesn't actually do anything (other than giving us 42bf215546Sopenharmony_ci * the offset) 43bf215546Sopenharmony_ci */ 44bf215546Sopenharmony_ci ret = 45bf215546Sopenharmony_ci drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req)); 46bf215546Sopenharmony_ci if (ret) { 47bf215546Sopenharmony_ci ERROR_MSG("alloc failed: %s", strerror(errno)); 48bf215546Sopenharmony_ci return ret; 49bf215546Sopenharmony_ci } 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci msm_bo->offset = req.value; 52bf215546Sopenharmony_ci } 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci return 0; 55bf215546Sopenharmony_ci} 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_cistatic int 58bf215546Sopenharmony_cimsm_bo_offset(struct fd_bo *bo, uint64_t *offset) 59bf215546Sopenharmony_ci{ 60bf215546Sopenharmony_ci struct msm_bo *msm_bo = to_msm_bo(bo); 61bf215546Sopenharmony_ci int ret = bo_allocate(msm_bo); 62bf215546Sopenharmony_ci if (ret) 63bf215546Sopenharmony_ci return ret; 64bf215546Sopenharmony_ci *offset = msm_bo->offset; 65bf215546Sopenharmony_ci return 0; 66bf215546Sopenharmony_ci} 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_cistatic int 69bf215546Sopenharmony_cimsm_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op) 70bf215546Sopenharmony_ci{ 71bf215546Sopenharmony_ci struct drm_msm_gem_cpu_prep req = { 72bf215546Sopenharmony_ci .handle = bo->handle, 73bf215546Sopenharmony_ci .op = op, 74bf215546Sopenharmony_ci }; 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci get_abs_timeout(&req.timeout, PIPE_TIMEOUT_INFINITE); 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci return drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_CPU_PREP, &req, sizeof(req)); 79bf215546Sopenharmony_ci} 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_cistatic void 82bf215546Sopenharmony_cimsm_bo_cpu_fini(struct fd_bo *bo) 83bf215546Sopenharmony_ci{ 84bf215546Sopenharmony_ci struct drm_msm_gem_cpu_fini req = { 85bf215546Sopenharmony_ci .handle = bo->handle, 86bf215546Sopenharmony_ci }; 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_CPU_FINI, &req, sizeof(req)); 89bf215546Sopenharmony_ci} 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_cistatic int 92bf215546Sopenharmony_cimsm_bo_madvise(struct fd_bo *bo, int willneed) 93bf215546Sopenharmony_ci{ 94bf215546Sopenharmony_ci struct drm_msm_gem_madvise req = { 95bf215546Sopenharmony_ci .handle = bo->handle, 96bf215546Sopenharmony_ci .madv = willneed ? MSM_MADV_WILLNEED : MSM_MADV_DONTNEED, 97bf215546Sopenharmony_ci }; 98bf215546Sopenharmony_ci int ret; 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci /* older kernels do not support this: */ 101bf215546Sopenharmony_ci if (bo->dev->version < FD_VERSION_MADVISE) 102bf215546Sopenharmony_ci return willneed; 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci ret = 105bf215546Sopenharmony_ci drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_MADVISE, &req, sizeof(req)); 106bf215546Sopenharmony_ci if (ret) 107bf215546Sopenharmony_ci return ret; 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci return req.retained; 110bf215546Sopenharmony_ci} 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_cistatic uint64_t 113bf215546Sopenharmony_cimsm_bo_iova(struct fd_bo *bo) 114bf215546Sopenharmony_ci{ 115bf215546Sopenharmony_ci struct drm_msm_gem_info req = { 116bf215546Sopenharmony_ci .handle = bo->handle, 117bf215546Sopenharmony_ci .info = MSM_INFO_GET_IOVA, 118bf215546Sopenharmony_ci }; 119bf215546Sopenharmony_ci int ret; 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci ret = drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req)); 122bf215546Sopenharmony_ci if (ret) 123bf215546Sopenharmony_ci return 0; 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci return req.value; 126bf215546Sopenharmony_ci} 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_cistatic void 129bf215546Sopenharmony_cimsm_bo_set_name(struct fd_bo *bo, const char *fmt, va_list ap) 130bf215546Sopenharmony_ci{ 131bf215546Sopenharmony_ci struct drm_msm_gem_info req = { 132bf215546Sopenharmony_ci .handle = bo->handle, 133bf215546Sopenharmony_ci .info = MSM_INFO_SET_NAME, 134bf215546Sopenharmony_ci }; 135bf215546Sopenharmony_ci char buf[32]; 136bf215546Sopenharmony_ci int sz; 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci if (bo->dev->version < FD_VERSION_SOFTPIN) 139bf215546Sopenharmony_ci return; 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci sz = vsnprintf(buf, sizeof(buf), fmt, ap); 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci req.value = VOID2U64(buf); 144bf215546Sopenharmony_ci req.len = MIN2(sz, sizeof(buf)); 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req)); 147bf215546Sopenharmony_ci} 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_cistatic void 150bf215546Sopenharmony_cimsm_bo_destroy(struct fd_bo *bo) 151bf215546Sopenharmony_ci{ 152bf215546Sopenharmony_ci struct msm_bo *msm_bo = to_msm_bo(bo); 153bf215546Sopenharmony_ci free(msm_bo); 154bf215546Sopenharmony_ci} 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_cistatic const struct fd_bo_funcs funcs = { 157bf215546Sopenharmony_ci .offset = msm_bo_offset, 158bf215546Sopenharmony_ci .cpu_prep = msm_bo_cpu_prep, 159bf215546Sopenharmony_ci .cpu_fini = msm_bo_cpu_fini, 160bf215546Sopenharmony_ci .madvise = msm_bo_madvise, 161bf215546Sopenharmony_ci .iova = msm_bo_iova, 162bf215546Sopenharmony_ci .set_name = msm_bo_set_name, 163bf215546Sopenharmony_ci .destroy = msm_bo_destroy, 164bf215546Sopenharmony_ci}; 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci/* allocate a buffer handle: */ 167bf215546Sopenharmony_cistatic int 168bf215546Sopenharmony_cinew_handle(struct fd_device *dev, uint32_t size, uint32_t flags, uint32_t *handle) 169bf215546Sopenharmony_ci{ 170bf215546Sopenharmony_ci struct drm_msm_gem_new req = { 171bf215546Sopenharmony_ci .size = size, 172bf215546Sopenharmony_ci }; 173bf215546Sopenharmony_ci int ret; 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci if (flags & FD_BO_SCANOUT) 176bf215546Sopenharmony_ci req.flags |= MSM_BO_SCANOUT; 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci if (flags & FD_BO_GPUREADONLY) 179bf215546Sopenharmony_ci req.flags |= MSM_BO_GPU_READONLY; 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci if (flags & FD_BO_CACHED_COHERENT) 182bf215546Sopenharmony_ci req.flags |= MSM_BO_CACHED_COHERENT; 183bf215546Sopenharmony_ci else 184bf215546Sopenharmony_ci req.flags |= MSM_BO_WC; 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci ret = drmCommandWriteRead(dev->fd, DRM_MSM_GEM_NEW, &req, sizeof(req)); 187bf215546Sopenharmony_ci if (ret) 188bf215546Sopenharmony_ci return ret; 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci *handle = req.handle; 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci return 0; 193bf215546Sopenharmony_ci} 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci/* allocate a new buffer object */ 196bf215546Sopenharmony_cistruct fd_bo * 197bf215546Sopenharmony_cimsm_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags) 198bf215546Sopenharmony_ci{ 199bf215546Sopenharmony_ci uint32_t handle; 200bf215546Sopenharmony_ci int ret; 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci ret = new_handle(dev, size, flags, &handle); 203bf215546Sopenharmony_ci if (ret) 204bf215546Sopenharmony_ci return NULL; 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci return msm_bo_from_handle(dev, size, handle); 207bf215546Sopenharmony_ci} 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci/* allocate a new buffer object from existing handle (import) */ 210bf215546Sopenharmony_cistruct fd_bo * 211bf215546Sopenharmony_cimsm_bo_from_handle(struct fd_device *dev, uint32_t size, uint32_t handle) 212bf215546Sopenharmony_ci{ 213bf215546Sopenharmony_ci struct msm_bo *msm_bo; 214bf215546Sopenharmony_ci struct fd_bo *bo; 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci msm_bo = calloc(1, sizeof(*msm_bo)); 217bf215546Sopenharmony_ci if (!msm_bo) 218bf215546Sopenharmony_ci return NULL; 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci bo = &msm_bo->base; 221bf215546Sopenharmony_ci bo->size = size; 222bf215546Sopenharmony_ci bo->handle = handle; 223bf215546Sopenharmony_ci bo->funcs = &funcs; 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci fd_bo_init_common(bo, dev); 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci return bo; 228bf215546Sopenharmony_ci} 229