[12/12] drm/amdgpu: enable foreign DMA-buf objects

Submitted by Kuehling, Felix on July 3, 2017, 9:11 p.m.

Details

Message ID 1499116294-12817-13-git-send-email-Felix.Kuehling@amd.com
State New
Headers show
Series "Patches from amd-kfd-staging" ( rev: 3 2 1 ) in AMD X.Org drivers

Not browsing as part of any series.

Commit Message

Kuehling, Felix July 3, 2017, 9:11 p.m.
From: Christian König <christian.koenig@amd.com>

We should be able to handle BOs from other instances as well.

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Felix Kuehling <Felix.Kuehling@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(-)

Patch hide | download patch | download mbox

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;
+
+	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);
+}

Comments

Am 03.07.2017 um 23:11 schrieb Felix Kuehling:
> From: Christian König <christian.koenig@amd.com>
>
> We should be able to handle BOs from other instances as well.
>
> Signed-off-by: Christian König <christian.koenig@amd.com>
> Reviewed-by: Felix Kuehling <Felix.Kuehling@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);
> +}