diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 5525628e6d24..1810f67748cc 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -564,6 +564,68 @@ static const struct dma_buf_ops rockchip_drm_gem_prime_dmabuf_ops = { .end_cpu_access = rockchip_drm_gem_dmabuf_end_cpu_access, }; +static struct drm_gem_object *rockchip_drm_gem_prime_import_dev(struct drm_device *dev, + struct dma_buf *dma_buf, + struct device *attach_dev) +{ + struct dma_buf_attachment *attach; + struct sg_table *sgt; + struct drm_gem_object *obj; + int ret; + + if (dma_buf->ops == &rockchip_drm_gem_prime_dmabuf_ops) { + obj = dma_buf->priv; + if (obj->dev == dev) { + /* + * Importing dmabuf exported from out own gem increases + * refcount on gem itself instead of f_count of dmabuf. + */ + drm_gem_object_get(obj); + return obj; + } + } + + if (!dev->driver->gem_prime_import_sg_table) + return ERR_PTR(-EINVAL); + + attach = dma_buf_attach(dma_buf, attach_dev); + if (IS_ERR(attach)) + return ERR_CAST(attach); + + get_dma_buf(dma_buf); + + sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); + if (IS_ERR(sgt)) { + ret = PTR_ERR(sgt); + goto fail_detach; + } + + obj = dev->driver->gem_prime_import_sg_table(dev, attach, sgt); + if (IS_ERR(obj)) { + ret = PTR_ERR(obj); + goto fail_unmap; + } + + obj->import_attach = attach; + obj->resv = dma_buf->resv; + + return obj; + +fail_unmap: + dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); +fail_detach: + dma_buf_detach(dma_buf, attach); + dma_buf_put(dma_buf); + + return ERR_PTR(ret); +} + +static struct drm_gem_object *rockchip_drm_gem_prime_import(struct drm_device *dev, + struct dma_buf *dma_buf) +{ + return rockchip_drm_gem_prime_import_dev(dev, dma_buf, dev->dev); +} + static struct dma_buf *rockchip_drm_gem_prime_export(struct drm_gem_object *obj, int flags) { @@ -589,7 +651,7 @@ static struct drm_driver rockchip_drm_driver = { .dumb_create = rockchip_gem_dumb_create, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_import = drm_gem_prime_import, + .gem_prime_import = rockchip_drm_gem_prime_import, .gem_prime_export = rockchip_drm_gem_prime_export, .gem_prime_get_sg_table = rockchip_gem_prime_get_sg_table, .gem_prime_import_sg_table = rockchip_gem_prime_import_sg_table,