1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2018 Google, Inc. 3b8e80941Smrg * Copyright © 2015 Intel Corporation 4b8e80941Smrg * 5b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 7b8e80941Smrg * to deal in the Software without restriction, including without limitation 8b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 10b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 11b8e80941Smrg * 12b8e80941Smrg * The above copyright notice and this permission notice (including the next 13b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 14b8e80941Smrg * Software. 15b8e80941Smrg * 16b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22b8e80941Smrg * DEALINGS IN THE SOFTWARE. 23b8e80941Smrg */ 24b8e80941Smrg 25b8e80941Smrg#include "tu_private.h" 26b8e80941Smrg 27b8e80941Smrg#include <errno.h> 28b8e80941Smrg#include <fcntl.h> 29b8e80941Smrg#include <stdint.h> 30b8e80941Smrg#include <sys/ioctl.h> 31b8e80941Smrg#include <xf86drm.h> 32b8e80941Smrg 33b8e80941Smrg#include "drm/msm_drm.h" 34b8e80941Smrg 35b8e80941Smrgstatic int 36b8e80941Smrgtu_drm_get_param(const struct tu_physical_device *dev, 37b8e80941Smrg uint32_t param, 38b8e80941Smrg uint64_t *value) 39b8e80941Smrg{ 40b8e80941Smrg /* Technically this requires a pipe, but the kernel only supports one pipe 41b8e80941Smrg * anyway at the time of writing and most of these are clearly pipe 42b8e80941Smrg * independent. */ 43b8e80941Smrg struct drm_msm_param req = { 44b8e80941Smrg .pipe = MSM_PIPE_3D0, 45b8e80941Smrg .param = param, 46b8e80941Smrg }; 47b8e80941Smrg 48b8e80941Smrg int ret = drmCommandWriteRead(dev->local_fd, DRM_MSM_GET_PARAM, &req, 49b8e80941Smrg sizeof(req)); 50b8e80941Smrg if (ret) 51b8e80941Smrg return ret; 52b8e80941Smrg 53b8e80941Smrg *value = req.value; 54b8e80941Smrg 55b8e80941Smrg return 0; 56b8e80941Smrg} 57b8e80941Smrg 58b8e80941Smrgint 59b8e80941Smrgtu_drm_get_gpu_id(const struct tu_physical_device *dev, uint32_t *id) 60b8e80941Smrg{ 61b8e80941Smrg uint64_t value; 62b8e80941Smrg int ret = tu_drm_get_param(dev, MSM_PARAM_GPU_ID, &value); 63b8e80941Smrg if (ret) 64b8e80941Smrg return ret; 65b8e80941Smrg 66b8e80941Smrg *id = value; 67b8e80941Smrg return 0; 68b8e80941Smrg} 69b8e80941Smrg 70b8e80941Smrgint 71b8e80941Smrgtu_drm_get_gmem_size(const struct tu_physical_device *dev, uint32_t *size) 72b8e80941Smrg{ 73b8e80941Smrg uint64_t value; 74b8e80941Smrg int ret = tu_drm_get_param(dev, MSM_PARAM_GMEM_SIZE, &value); 75b8e80941Smrg if (ret) 76b8e80941Smrg return ret; 77b8e80941Smrg 78b8e80941Smrg *size = value; 79b8e80941Smrg return 0; 80b8e80941Smrg} 81b8e80941Smrg 82b8e80941Smrgint 83b8e80941Smrgtu_drm_submitqueue_new(const struct tu_device *dev, 84b8e80941Smrg int priority, 85b8e80941Smrg uint32_t *queue_id) 86b8e80941Smrg{ 87b8e80941Smrg struct drm_msm_submitqueue req = { 88b8e80941Smrg .flags = 0, 89b8e80941Smrg .prio = priority, 90b8e80941Smrg }; 91b8e80941Smrg 92b8e80941Smrg int ret = drmCommandWriteRead(dev->physical_device->local_fd, 93b8e80941Smrg DRM_MSM_SUBMITQUEUE_NEW, &req, sizeof(req)); 94b8e80941Smrg if (ret) 95b8e80941Smrg return ret; 96b8e80941Smrg 97b8e80941Smrg *queue_id = req.id; 98b8e80941Smrg return 0; 99b8e80941Smrg} 100b8e80941Smrg 101b8e80941Smrgvoid 102b8e80941Smrgtu_drm_submitqueue_close(const struct tu_device *dev, uint32_t queue_id) 103b8e80941Smrg{ 104b8e80941Smrg drmCommandWrite(dev->physical_device->local_fd, DRM_MSM_SUBMITQUEUE_CLOSE, 105b8e80941Smrg &queue_id, sizeof(uint32_t)); 106b8e80941Smrg} 107b8e80941Smrg 108b8e80941Smrg/** 109b8e80941Smrg * Return gem handle on success. Return 0 on failure. 110b8e80941Smrg */ 111b8e80941Smrguint32_t 112b8e80941Smrgtu_gem_new(const struct tu_device *dev, uint64_t size, uint32_t flags) 113b8e80941Smrg{ 114b8e80941Smrg struct drm_msm_gem_new req = { 115b8e80941Smrg .size = size, 116b8e80941Smrg .flags = flags, 117b8e80941Smrg }; 118b8e80941Smrg 119b8e80941Smrg int ret = drmCommandWriteRead(dev->physical_device->local_fd, 120b8e80941Smrg DRM_MSM_GEM_NEW, &req, sizeof(req)); 121b8e80941Smrg if (ret) 122b8e80941Smrg return 0; 123b8e80941Smrg 124b8e80941Smrg return req.handle; 125b8e80941Smrg} 126b8e80941Smrg 127b8e80941Smrguint32_t 128b8e80941Smrgtu_gem_import_dmabuf(const struct tu_device *dev, int prime_fd, uint64_t size) 129b8e80941Smrg{ 130b8e80941Smrg /* lseek() to get the real size */ 131b8e80941Smrg off_t real_size = lseek(prime_fd, 0, SEEK_END); 132b8e80941Smrg lseek(prime_fd, 0, SEEK_SET); 133b8e80941Smrg if (real_size < 0 || (uint64_t) real_size < size) 134b8e80941Smrg return 0; 135b8e80941Smrg 136b8e80941Smrg uint32_t gem_handle; 137b8e80941Smrg int ret = drmPrimeFDToHandle(dev->physical_device->local_fd, prime_fd, 138b8e80941Smrg &gem_handle); 139b8e80941Smrg if (ret) 140b8e80941Smrg return 0; 141b8e80941Smrg 142b8e80941Smrg return gem_handle; 143b8e80941Smrg} 144b8e80941Smrg 145b8e80941Smrgint 146b8e80941Smrgtu_gem_export_dmabuf(const struct tu_device *dev, uint32_t gem_handle) 147b8e80941Smrg{ 148b8e80941Smrg int prime_fd; 149b8e80941Smrg int ret = drmPrimeHandleToFD(dev->physical_device->local_fd, gem_handle, 150b8e80941Smrg DRM_CLOEXEC, &prime_fd); 151b8e80941Smrg 152b8e80941Smrg return ret == 0 ? prime_fd : -1; 153b8e80941Smrg} 154b8e80941Smrg 155b8e80941Smrgvoid 156b8e80941Smrgtu_gem_close(const struct tu_device *dev, uint32_t gem_handle) 157b8e80941Smrg{ 158b8e80941Smrg struct drm_gem_close req = { 159b8e80941Smrg .handle = gem_handle, 160b8e80941Smrg }; 161b8e80941Smrg 162b8e80941Smrg drmIoctl(dev->physical_device->local_fd, DRM_IOCTL_GEM_CLOSE, &req); 163b8e80941Smrg} 164b8e80941Smrg 165b8e80941Smrg/** Return UINT64_MAX on error. */ 166b8e80941Smrgstatic uint64_t 167b8e80941Smrgtu_gem_info(const struct tu_device *dev, uint32_t gem_handle, uint32_t info) 168b8e80941Smrg{ 169b8e80941Smrg struct drm_msm_gem_info req = { 170b8e80941Smrg .handle = gem_handle, 171b8e80941Smrg .info = info, 172b8e80941Smrg }; 173b8e80941Smrg 174b8e80941Smrg int ret = drmCommandWriteRead(dev->physical_device->local_fd, 175b8e80941Smrg DRM_MSM_GEM_INFO, &req, sizeof(req)); 176b8e80941Smrg if (ret == -1) 177b8e80941Smrg return UINT64_MAX; 178b8e80941Smrg 179b8e80941Smrg return req.value; 180b8e80941Smrg} 181b8e80941Smrg 182b8e80941Smrg/** Return UINT64_MAX on error. */ 183b8e80941Smrguint64_t 184b8e80941Smrgtu_gem_info_offset(const struct tu_device *dev, uint32_t gem_handle) 185b8e80941Smrg{ 186b8e80941Smrg return tu_gem_info(dev, gem_handle, MSM_INFO_GET_OFFSET); 187b8e80941Smrg} 188b8e80941Smrg 189b8e80941Smrg/** Return UINT64_MAX on error. */ 190b8e80941Smrguint64_t 191b8e80941Smrgtu_gem_info_iova(const struct tu_device *dev, uint32_t gem_handle) 192b8e80941Smrg{ 193b8e80941Smrg return tu_gem_info(dev, gem_handle, MSM_INFO_GET_IOVA); 194b8e80941Smrg} 195