[PATCH] drm/ast: add dmabuf/prime buffer sharing support

Thomas Zimmermann tzimmermann at suse.de
Mon Jul 18 09:32:37 UTC 2022


Hi

Am 18.07.22 um 03:45 schrieb oushixiong:
> This patch adds ast specific codes for DRM Prime feature.
> User application can get file descriptor from gem handle and also
> gem handle from file descriptor.this is to allow for offloading
> of rendering in one direction and outputs in the other.
> 
> Signed-off-by: oushixiong <oushixiong at kylinos.cn>
> ---
>   drivers/gpu/drm/ast/ast_drv.c  |  16 +++-
>   drivers/gpu/drm/ast/ast_drv.h  |  19 ++++-
>   drivers/gpu/drm/ast/ast_main.c | 115 ++++++++++++++++++++++++++++-
>   drivers/gpu/drm/ast/ast_ttm.c  | 130 ++++++++++++++++++++++++++++++++-

Your copy of the source code is way too old. Some of these files have 
been remove years ago. The most recent development tree is drm-tip at

   https://cgit.freedesktop.org/drm/drm-tip/

Best regards
Thomas

>   4 files changed, 273 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c
> index bf589c53b908..084d0c8b0f6b 100644
> --- a/drivers/gpu/drm/ast/ast_drv.c
> +++ b/drivers/gpu/drm/ast/ast_drv.c
> @@ -214,7 +214,7 @@ static const struct file_operations ast_fops = {
>   };
>   
>   static struct drm_driver driver = {
> -	.driver_features = DRIVER_MODESET | DRIVER_GEM,
> +	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
>   
>   	.load = ast_driver_load,
>   	.unload = ast_driver_unload,
> @@ -231,6 +231,20 @@ static struct drm_driver driver = {
>   	.dumb_create = ast_dumb_create,
>   	.dumb_map_offset = ast_dumb_mmap_offset,
>   
> +	.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_export       = drm_gem_prime_export,
> +
> +	.gem_prime_get_sg_table = ast_gem_prime_get_sg_table,
> +	.gem_prime_import_sg_table = ast_gem_prime_import_sg_table,
> +	.gem_prime_vmap         = ast_gem_prime_vmap,
> +	.gem_prime_vunmap       = ast_gem_prime_vunmap,
> +	.gem_prime_pin          = ast_gem_prime_pin,
> +	.gem_prime_unpin        = ast_gem_prime_unpin,
> +
> +	.gem_prime_res_obj = ast_gem_prime_res_obj,
> +
>   };
>   
>   static int __init ast_init(void)
> diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
> index e6c4cd3dc50e..b19b9aa5a517 100644
> --- a/drivers/gpu/drm/ast/ast_drv.h
> +++ b/drivers/gpu/drm/ast/ast_drv.h
> @@ -258,6 +258,7 @@ struct ast_encoder {
>   struct ast_framebuffer {
>   	struct drm_framebuffer base;
>   	struct drm_gem_object *obj;
> +	void *vmapping;
>   };
>   
>   struct ast_fbdev {
> @@ -330,6 +331,7 @@ struct ast_bo {
>   	struct drm_gem_object gem;
>   	struct ttm_place placements[3];
>   	int pin_count;
> +	struct ttm_bo_kmap_obj dma_buf_vmap;
>   };
>   #define gem_to_ast_bo(gobj) container_of((gobj), struct ast_bo, gem)
>   
> @@ -361,7 +363,9 @@ int ast_mm_init(struct ast_private *ast);
>   void ast_mm_fini(struct ast_private *ast);
>   
>   int ast_bo_create(struct drm_device *dev, int size, int align,
> -		  uint32_t flags, struct ast_bo **pastbo);
> +		uint32_t flags, struct sg_table *sg,
> +		struct reservation_object *resv,
> +		struct ast_bo **pastbo);
>   
>   int ast_gem_create(struct drm_device *dev,
>   		   u32 size, bool iskernel,
> @@ -369,6 +373,19 @@ int ast_gem_create(struct drm_device *dev,
>   
>   int ast_bo_pin(struct ast_bo *bo, u32 pl_flag, u64 *gpu_addr);
>   int ast_bo_unpin(struct ast_bo *bo);
> +struct sg_table *ast_gem_prime_get_sg_table(struct drm_gem_object *obj);
> +void *ast_gem_prime_vmap(struct drm_gem_object *obj);
> +void ast_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
> +
> +struct drm_gem_object *ast_gem_prime_import_sg_table(struct drm_device *dev,
> +			struct dma_buf_attachment *attach,
> +			struct sg_table *sg);
> +
> +int ast_gem_prime_pin(struct drm_gem_object *obj);
> +void ast_gem_prime_unpin(struct drm_gem_object *obj);
> +
> +struct reservation_object *ast_gem_prime_res_obj(struct drm_gem_object *obj);
> +
>   
>   static inline int ast_bo_reserve(struct ast_bo *bo, bool no_wait)
>   {
> diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
> index 224fa1ef87ff..6f8fc49b062c 100644
> --- a/drivers/gpu/drm/ast/ast_main.c
> +++ b/drivers/gpu/drm/ast/ast_main.c
> @@ -28,7 +28,7 @@
>   #include <drm/drmP.h>
>   #include "ast_drv.h"
>   
> -
> +#include <linux/dma-buf.h>
>   #include <drm/drm_fb_helper.h>
>   #include <drm/drm_crtc_helper.h>
>   
> @@ -383,17 +383,125 @@ static int ast_get_dram_info(struct drm_device *dev)
>   	return 0;
>   }
>   
> +int ast_handle_damage(struct ast_framebuffer *fb, int x, int y,
> +			int width, int height)
> +{
> +	struct ast_bo *dst_bo = NULL;
> +	void *dst = NULL;
> +	int ret = 0, i;
> +	unsigned long offset = 0;
> +	bool unmap = false;
> +	unsigned int bytesPerPixel;
> +
> +	bytesPerPixel = fb->base.format->cpp[0];
> +
> +	if (!fb->obj->import_attach)
> +		return -EINVAL;
> +
> +	if (!fb->vmapping) {
> +		fb->vmapping = dma_buf_vmap(fb->obj->import_attach->dmabuf);
> +		if (!fb->vmapping)
> +			return 0;
> +	}
> +	dst_bo = gem_to_ast_bo(fb->obj);
> +	ret = ast_bo_reserve(dst_bo, true);
> +	if (ret) {
> +		DRM_ERROR("ast_bo_reserve failed\n");
> +		ast_bo_unreserve(dst_bo);
> +		goto error;
> +	}
> +	if (!dst_bo->dma_buf_vmap.virtual) {
> +		ret = ttm_bo_kmap(&dst_bo->bo, 0,
> +			dst_bo->bo.num_pages, &dst_bo->dma_buf_vmap);
> +		if (ret) {
> +			DRM_ERROR("failed to kmap fbcon\n");
> +			goto error;
> +		}
> +		unmap = true;
> +	}
> +	dst = dst_bo->dma_buf_vmap.virtual;
> +
> +	for (i = y; i < y + height; i++) {
> +		offset = i * fb->base.pitches[0] + (x * bytesPerPixel);
> +		memcpy_toio(dst + offset, fb->vmapping + offset,
> +			width * bytesPerPixel);
> +	}
> +
> +	if (unmap)
> +		ttm_bo_kunmap(&dst_bo->dma_buf_vmap);
> +	ast_bo_unreserve(dst_bo);
> +
> +error:
> +	return 0;
> +}
> +
>   static void ast_user_framebuffer_destroy(struct drm_framebuffer *fb)
>   {
>   	struct ast_framebuffer *ast_fb = to_ast_framebuffer(fb);
>   
> +	if (ast_fb->obj->import_attach) {
> +		if (ast_fb->vmapping)
> +			dma_buf_vunmap(ast_fb->obj->import_attach->dmabuf,
> +				ast_fb->vmapping);
> +	}
> +
>   	drm_gem_object_put_unlocked(ast_fb->obj);
>   	drm_framebuffer_cleanup(fb);
>   	kfree(ast_fb);
>   }
>   
> +static int ast_user_framebuffer_dirty(struct drm_framebuffer *fb,
> +				struct drm_file *file,
> +				unsigned int flags,
> +				unsigned int color,
> +				struct drm_clip_rect *clips,
> +				unsigned int num_clips)
> +{
> +	struct ast_framebuffer *ast_fb = to_ast_framebuffer(fb);
> +	int i, ret = 0;
> +
> +	drm_modeset_lock_all(fb->dev);
> +
> +	if (ast_fb->obj->import_attach) {
> +		ret = dma_buf_begin_cpu_access(
> +				ast_fb->obj->import_attach->dmabuf,
> +				DMA_FROM_DEVICE);
> +		if (ret)
> +			goto unlock;
> +		}
> +
> +	for (i = 0; i < num_clips; i++) {
> +		ret = ast_handle_damage(ast_fb, clips[i].x1, clips[i].y1,
> +			clips[i].x2 - clips[i].x1,
> +			clips[i].y2 - clips[i].y1);
> +		if (ret)
> +			break;
> +	}
> +
> +	if (ast_fb->obj->import_attach) {
> +		dma_buf_end_cpu_access(ast_fb->obj->import_attach->dmabuf,
> +			DMA_FROM_DEVICE);
> +	}
> +
> +unlock:
> +	drm_modeset_unlock_all(fb->dev);
> +
> +	return ret;
> +}
> +
> +static int ast_user_framebuffer_create_handle(struct drm_framebuffer *fb,
> +			struct drm_file *file_priv,
> +			unsigned int *handle)
> +{
> +	struct ast_framebuffer *ast_fb = to_ast_framebuffer(fb);
> +
> +	return drm_gem_handle_create(file_priv, ast_fb->obj, handle);
> +}
> +
>   static const struct drm_framebuffer_funcs ast_fb_funcs = {
> +	.create_handle = ast_user_framebuffer_create_handle,
>   	.destroy = ast_user_framebuffer_destroy,
> +	.dirty = ast_user_framebuffer_dirty,
>   };
>   
>   
> @@ -605,7 +713,7 @@ int ast_gem_create(struct drm_device *dev,
>   	if (size == 0)
>   		return -EINVAL;
>   
> -	ret = ast_bo_create(dev, size, 0, 0, &astbo);
> +	ret = ast_bo_create(dev, size, 0, 0, NULL, NULL, &astbo);
>   	if (ret) {
>   		if (ret != -ERESTARTSYS)
>   			DRM_ERROR("failed to allocate GEM object\n");
> @@ -656,6 +764,9 @@ void ast_gem_free_object(struct drm_gem_object *obj)
>   {
>   	struct ast_bo *ast_bo = gem_to_ast_bo(obj);
>   
> +	if (ast_bo->gem.import_attach)
> +		drm_prime_gem_destroy(&ast_bo->gem, ast_bo->bo.sg);
> +
>   	ast_bo_unref(&ast_bo);
>   }
>   
> diff --git a/drivers/gpu/drm/ast/ast_ttm.c b/drivers/gpu/drm/ast/ast_ttm.c
> index fe354ebf374d..fea0429407e0 100644
> --- a/drivers/gpu/drm/ast/ast_ttm.c
> +++ b/drivers/gpu/drm/ast/ast_ttm.c
> @@ -27,6 +27,7 @@
>    */
>   #include <drm/drmP.h>
>   #include <drm/ttm/ttm_page_alloc.h>
> +#include <linux/dma-buf.h>
>   
>   #include "ast_drv.h"
>   
> @@ -215,8 +216,38 @@ static struct ttm_tt *ast_ttm_tt_create(struct ttm_buffer_object *bo,
>   	return tt;
>   }
>   
> +static int ast_ttm_tt_populate(struct ttm_tt *ttm,
> +			struct ttm_operation_ctx *ctx)
> +{
> +	bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
> +
> +	if (ttm->state != tt_unpopulated)
> +		return 0;
> +
> +	if (slave && ttm->sg) {
> +		drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages,
> +				NULL, ttm->num_pages);
> +		ttm->state = tt_unbound;
> +		return 0;
> +	}
> +
> +	return ttm_pool_populate(ttm, ctx);
> +}
> +
> +static void ast_ttm_tt_unpopulate(struct ttm_tt *ttm)
> +{
> +	bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
> +
> +	if (slave)
> +		return;
> +
> +	ttm_pool_unpopulate(ttm);
> +}
> +
>   struct ttm_bo_driver ast_bo_driver = {
>   	.ttm_tt_create = ast_ttm_tt_create,
> +	.ttm_tt_populate = ast_ttm_tt_populate,
> +	.ttm_tt_unpopulate = ast_ttm_tt_unpopulate,
>   	.init_mem_type = ast_bo_init_mem_type,
>   	.eviction_valuable = ttm_bo_eviction_valuable,
>   	.evict_flags = ast_bo_evict_flags,
> @@ -297,13 +328,21 @@ void ast_ttm_placement(struct ast_bo *bo, int domain)
>   }
>   
>   int ast_bo_create(struct drm_device *dev, int size, int align,
> -		  uint32_t flags, struct ast_bo **pastbo)
> +		  uint32_t flags, struct sg_table *sg,
> +		  struct reservation_object *resv,
> +		  struct ast_bo **pastbo)
>   {
>   	struct ast_private *ast = dev->dev_private;
>   	struct ast_bo *astbo;
>   	size_t acc_size;
> +	enum ttm_bo_type type;
>   	int ret;
>   
> +	if (sg)
> +		type = ttm_bo_type_sg;
> +	else
> +		type = ttm_bo_type_device;
> +
>   	astbo = kzalloc(sizeof(struct ast_bo), GFP_KERNEL);
>   	if (!astbo)
>   		return -ENOMEM;
> @@ -320,9 +359,9 @@ int ast_bo_create(struct drm_device *dev, int size, int align,
>   				       sizeof(struct ast_bo));
>   
>   	ret = ttm_bo_init(&ast->ttm.bdev, &astbo->bo, size,
> -			  ttm_bo_type_device, &astbo->placement,
> +			  type, &astbo->placement,
>   			  align >> PAGE_SHIFT, false, acc_size,
> -			  NULL, NULL, ast_bo_ttm_destroy);
> +			  sg, resv, ast_bo_ttm_destroy);
>   	if (ret)
>   		goto error;
>   
> @@ -418,3 +457,88 @@ int ast_mmap(struct file *filp, struct vm_area_struct *vma)
>   	ast = file_priv->minor->dev->dev_private;
>   	return ttm_bo_mmap(filp, vma, &ast->ttm.bdev);
>   }
> +
> +struct sg_table *ast_gem_prime_get_sg_table(struct drm_gem_object *obj)
> +{
> +	struct ast_bo *bo = gem_to_ast_bo(obj);
> +	int npages = bo->bo.num_pages;
> +
> +	return drm_prime_pages_to_sg(bo->bo.ttm->pages, npages);
> +}
> +
> +void *ast_gem_prime_vmap(struct drm_gem_object *obj)
> +{
> +	struct ast_bo *bo = gem_to_ast_bo(obj);
> +	int ret;
> +
> +	ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages,
> +			&bo->dma_buf_vmap);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	return bo->dma_buf_vmap.virtual;
> +}
> +
> +void ast_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
> +{
> +	struct ast_bo *bo = gem_to_ast_bo(obj);
> +
> +	ttm_bo_kunmap(&bo->dma_buf_vmap);
> +}
> +
> +struct drm_gem_object *ast_gem_prime_import_sg_table(struct drm_device *dev,
> +				struct dma_buf_attachment *attach,
> +				struct sg_table *sg)
> +{
> +	struct ast_bo *bo;
> +	int ret;
> +
> +	struct reservation_object *resv = attach->dmabuf->resv;
> +
> +	ww_mutex_lock(&resv->lock, NULL);
> +	ret = ast_bo_create(dev, attach->dmabuf->size,
> +			PAGE_SIZE, 0, sg, resv, &bo);
> +	ww_mutex_unlock(&resv->lock);
> +
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	return &bo->gem;
> +}
> +
> +int ast_gem_prime_pin(struct drm_gem_object *obj)
> +{
> +	struct ast_bo *bo  = gem_to_ast_bo(obj);
> +	int ret = 0;
> +
> +	ret = ast_bo_reserve(bo, false);
> +	if (unlikely(ret != 0))
> +		return ret;
> +
> +	/* pin buffer into GTT */
> +	ret = ast_bo_pin(bo, TTM_PL_FLAG_SYSTEM, NULL);
> +	ast_bo_unreserve(bo);
> +
> +	return ret;
> +}
> +
> +void ast_gem_prime_unpin(struct drm_gem_object *obj)
> +{
> +	struct ast_bo *bo = gem_to_ast_bo(obj);
> +	int ret = 0;
> +
> +	ret = ast_bo_reserve(bo, false);
> +	if (unlikely(ret != 0))
> +		return;
> +
> +	ast_bo_unpin(bo);
> +	ast_bo_unreserve(bo);
> +}
> +
> +struct reservation_object *ast_gem_prime_res_obj(struct drm_gem_object *obj)
> +{
> +	struct ast_bo *bo = gem_to_ast_bo(obj);
> +
> +	return bo->bo.resv;
> +}
> +

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20220718/fcf97640/attachment-0001.sig>


More information about the dri-devel mailing list