diff options
author | David Stevens <stevensd@chromium.org> | 2020-08-18 16:13:43 +0900 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2020-08-18 10:01:54 +0200 |
commit | c84adb304c100cb9555f64f49c1d84a01fac3616 (patch) | |
tree | a35bea4349013dfc48de5365903fab5e66ebab11 /drivers/gpu/drm/virtio/virtgpu_prime.c | |
parent | 592d9fba33c275b72cb4dae99c187444daafcd33 (diff) | |
download | linux-c84adb304c100cb9555f64f49c1d84a01fac3616.tar.bz2 |
drm/virtio: Support virtgpu exported resources
Add support for UUID-based resource sharing mechanism to virtgpu. This
implements the new virtgpu commands and hooks them up to dma-buf's
get_uuid callback.
Signed-off-by: David Stevens <stevensd@chromium.org>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20200818071343.3461203-4-stevensd@chromium.org
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/virtio/virtgpu_prime.c')
-rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_prime.c | 96 |
1 files changed, 93 insertions, 3 deletions
diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c index 050d24c39a8f..acd14ef73d56 100644 --- a/drivers/gpu/drm/virtio/virtgpu_prime.c +++ b/drivers/gpu/drm/virtio/virtgpu_prime.c @@ -23,12 +23,102 @@ */ #include <drm/drm_prime.h> +#include <linux/virtio_dma_buf.h> #include "virtgpu_drv.h" -/* Empty Implementations as there should not be any other driver for a virtual - * device that might share buffers with virtgpu - */ +static int virtgpu_virtio_get_uuid(struct dma_buf *buf, + uuid_t *uuid) +{ + struct drm_gem_object *obj = buf->priv; + struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj); + struct virtio_gpu_device *vgdev = obj->dev->dev_private; + + wait_event(vgdev->resp_wq, bo->uuid_state != UUID_INITIALIZING); + if (bo->uuid_state != UUID_INITIALIZED) + return -ENODEV; + + uuid_copy(uuid, &bo->uuid); + + return 0; +} + +const struct virtio_dma_buf_ops virtgpu_dmabuf_ops = { + .ops = { + .cache_sgt_mapping = true, + .attach = virtio_dma_buf_attach, + .detach = drm_gem_map_detach, + .map_dma_buf = drm_gem_map_dma_buf, + .unmap_dma_buf = drm_gem_unmap_dma_buf, + .release = drm_gem_dmabuf_release, + .mmap = drm_gem_dmabuf_mmap, + .vmap = drm_gem_dmabuf_vmap, + .vunmap = drm_gem_dmabuf_vunmap, + }, + .device_attach = drm_gem_map_attach, + .get_uuid = virtgpu_virtio_get_uuid, +}; + +struct dma_buf *virtgpu_gem_prime_export(struct drm_gem_object *obj, + int flags) +{ + struct dma_buf *buf; + struct drm_device *dev = obj->dev; + struct virtio_gpu_device *vgdev = dev->dev_private; + struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj); + struct virtio_gpu_object_array *objs; + int ret = 0; + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + + if (vgdev->has_resource_assign_uuid) { + objs = virtio_gpu_array_alloc(1); + if (!objs) + return ERR_PTR(-ENOMEM); + virtio_gpu_array_add_obj(objs, &bo->base.base); + + ret = virtio_gpu_cmd_resource_assign_uuid(vgdev, objs); + if (ret) + return ERR_PTR(ret); + virtio_gpu_notify(vgdev); + } else { + bo->uuid_state = UUID_INITIALIZATION_FAILED; + } + + exp_info.ops = &virtgpu_dmabuf_ops.ops; + exp_info.size = obj->size; + exp_info.flags = flags; + exp_info.priv = obj; + exp_info.resv = obj->resv; + + buf = virtio_dma_buf_export(&exp_info); + if (IS_ERR(buf)) + return buf; + + drm_dev_get(dev); + drm_gem_object_get(obj); + + return buf; +} + +struct drm_gem_object *virtgpu_gem_prime_import(struct drm_device *dev, + struct dma_buf *buf) +{ + struct drm_gem_object *obj; + + if (buf->ops == &virtgpu_dmabuf_ops.ops) { + obj = buf->priv; + if (obj->dev == dev) { + /* + * Importing dmabuf exported from our own gem increases + * refcount on gem itself instead of f_count of dmabuf. + */ + drm_gem_object_get(obj); + return obj; + } + } + + return drm_gem_prime_import(dev, buf); +} struct drm_gem_object *virtgpu_gem_prime_import_sg_table( struct drm_device *dev, struct dma_buf_attachment *attach, |