[PATCH 12/12] drm/amdgpu: enable foreign DMA-buf objects
Christian König
deathsimple at vodafone.de
Tue Jul 4 07:32:44 UTC 2017
Am 03.07.2017 um 23:11 schrieb Felix Kuehling:
> From: Christian König <christian.koenig at amd.com>
>
> We should be able to handle BOs from other instances as well.
>
> Signed-off-by: Christian König <christian.koenig at amd.com>
> Reviewed-by: Felix Kuehling <Felix.Kuehling at amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++
> drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 2 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c | 59 +++++++++++++++++++++++++++++++
> 3 files changed, 62 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index f3d99cb..18b2c28 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -468,6 +468,8 @@ struct drm_gem_object *
> struct dma_buf *amdgpu_gem_prime_export(struct drm_device *dev,
> struct drm_gem_object *gobj,
> int flags);
> +struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
> + struct dma_buf *dma_buf);
> int amdgpu_gem_prime_pin(struct drm_gem_object *obj);
> void amdgpu_gem_prime_unpin(struct drm_gem_object *obj);
> struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *);
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> index 02cf24e..df78a3a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> @@ -813,7 +813,7 @@ long amdgpu_drm_ioctl(struct file *filp,
> .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
> .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
> .gem_prime_export = amdgpu_gem_prime_export,
> - .gem_prime_import = drm_gem_prime_import,
> + .gem_prime_import = amdgpu_gem_prime_import,
> .gem_prime_pin = amdgpu_gem_prime_pin,
> .gem_prime_unpin = amdgpu_gem_prime_unpin,
> .gem_prime_res_obj = amdgpu_gem_prime_res_obj,
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
> index b9425ed..9f7fae8 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
> @@ -159,3 +159,62 @@ struct dma_buf *amdgpu_gem_prime_export(struct drm_device *dev,
>
> return drm_gem_prime_export(dev, gobj, flags);
> }
> +
> +static struct drm_gem_object *
> +amdgpu_gem_prime_foreign_bo(struct amdgpu_device *adev, struct amdgpu_bo *bo)
> +{
> + struct amdgpu_gem_object *gobj;
> + int r;
> +
> + ww_mutex_lock(&bo->tbo.resv->lock, NULL);
> +
> + list_for_each_entry(gobj, &bo->gem_objects, list) {
> + if (gobj->base.dev != adev->ddev)
> + continue;
> +
> + ww_mutex_unlock(&bo->tbo.resv->lock);
> + drm_gem_object_reference(&gobj->base);
> + return &gobj->base;
> + }
> +
> +
> + gobj = kzalloc(sizeof(struct amdgpu_gem_object), GFP_KERNEL);
> + if (unlikely(!gobj)) {
> + ww_mutex_unlock(&bo->tbo.resv->lock);
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + r = drm_gem_object_init(adev->ddev, &gobj->base, amdgpu_bo_size(bo));
> + if (unlikely(r)) {
> + kfree(gobj);
> + ww_mutex_unlock(&bo->tbo.resv->lock);
> + return ERR_PTR(r);
> + }
> +
> + list_add(&gobj->list, &bo->gem_objects);
> + gobj->bo = amdgpu_bo_ref(bo);
> + bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
It's a bit more tricker than that. IIRC my original patch limited the BO
to GTT space as well.
VRAM peer to peer access doesn't work with most PCIe chipsets.
At bare minimum we need to put this behind a config option or add a
white list for the chipset or only enable it if "pci=pcie_bus_peer2peer"
is set or something like this.
BTW: If you modify a patch as severely as that please add your
Signed-of-by line as well.
Regards,
Christian.
> +
> + ww_mutex_unlock(&bo->tbo.resv->lock);
> +
> + return &gobj->base;
> +}
> +
> +struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
> + struct dma_buf *dma_buf)
> +{
> + struct amdgpu_device *adev = dev->dev_private;
> +
> + if (dma_buf->ops == &drm_gem_prime_dmabuf_ops) {
> + struct drm_gem_object *obj = dma_buf->priv;
> +
> + if (obj->dev != dev && obj->dev->driver == dev->driver) {
> + /* It's a amdgpu_bo from a different driver instance */
> + struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
> +
> + return amdgpu_gem_prime_foreign_bo(adev, bo);
> + }
> + }
> +
> + return drm_gem_prime_import(dev, dma_buf);
> +}
More information about the amd-gfx
mailing list