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