[PATCH 1/4] [RFC] drm/exynos: DMABUF: Added support for exporting non-contig buffers

Inki Dae inki.dae at samsung.com
Sun Apr 15 19:09:07 PDT 2012


Hi Prathyush.

First of all, thanks for your patch but your patch set isn't considered for
latest exynos dmabuf. 
we already updated dmabuf support for exynos drm and this is also considered
for non-continuous memory region. you can refer to git repository below:
	
http://git.infradead.org/users/kmpark/linux-2.6-samsung/shortlog/refs/heads/
exynos-drm-prime

and this repository has already been tested by me and Tomasz. for this,
please refer to link below:
	http://www.spinics.net/lists/linux-media/msg46292.html

last week, we had posted exynos-drm-fixes update and it has been merged to
drm-fixes last week. so we are just waiting for drm-next update to post
latest exynos-drm-prime. sorry but please, re-sync your patch set with
latest Dave's drm-next after latest exynos-drm-prime is posted so your patch
set can't be reviewed yet.

Thanks,
Inki Dae.

> -----Original Message-----
> From: Prathyush [mailto:prathyush.k at samsung.com]
> Sent: Saturday, April 14, 2012 8:52 PM
> To: dri-devel at lists.freedesktop.org; linaro-mm-sig at lists.linaro.org
> Cc: inki.dae at samsung.com; subash.rp at samsung.com; prashanth.g at samsung.com;
> sunilm at samsung.com; prathyush.k at samsung.com
> Subject: [PATCH 1/4] [RFC] drm/exynos: DMABUF: Added support for exporting
> non-contig buffers
> 
> With this change, the exynos drm dmabuf module can export and
> import dmabuf of gem objects with non-continuous memory.
> 
> The exynos_map_dmabuf function can create SGT of a non-contiguous
> buffer by calling dma_get_pages to retrieve the allocated pages
> and then maps the SGT to the caller's address space.
> 
> Signed-off-by: Prathyush K <prathyush.k at samsung.com>
> ---
>  drivers/gpu/drm/exynos/exynos_drm_dmabuf.c |   98
+++++++++++++++++++++++-
> ----
>  1 files changed, 81 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
> b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
> index cbb6ad4..54b88bd 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
> @@ -56,6 +56,59 @@ static void exynos_dmabuf_detach(struct dma_buf
*dmabuf,
>  	dma_buf_put(dmabuf);
>  }
> 
> +
> +static struct sg_table *drm_dc_pages_to_sgt(struct page **pages,
> +	unsigned long n_pages, size_t offset, size_t offset2, dma_addr_t
> daddr)
> +{
> +	struct sg_table *sgt;
> +	struct scatterlist *s;
> +	int i, j, cur_page, chunks, ret;
> +
> +	sgt = kzalloc(sizeof *sgt, GFP_KERNEL);
> +	if (!sgt)
> +		return ERR_PTR(-ENOMEM);
> +
> +	/* compute number of chunks */
> +	chunks = 1;
> +	for (i = 1; i < n_pages; ++i)
> +		if (pages[i] != pages[i - 1] + 1)
> +			++chunks;
> +
> +	ret = sg_alloc_table(sgt, chunks, GFP_KERNEL);
> +	if (ret) {
> +		kfree(sgt);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	/* merging chunks and putting them into the scatterlist */
> +	cur_page = 0;
> +	for_each_sg(sgt->sgl, s, sgt->orig_nents, i) {
> +		size_t size = PAGE_SIZE;
> +
> +		for (j = cur_page + 1; j < n_pages; ++j) {
> +			if (pages[j] != pages[j - 1] + 1)
> +				break;
> +			size += PAGE_SIZE;
> +		}
> +
> +		/* cut offset if chunk starts at the first page */
> +		if (cur_page == 0)
> +			size -= offset;
> +		/* cut offset2 if chunk ends at the last page */
> +		if (j == n_pages)
> +			size -= offset2;
> +
> +		sg_set_page(s, pages[cur_page], size, offset);
> +		s->dma_address = daddr;
> +		daddr +=  size;
> +		offset = 0;
> +		cur_page = j;
> +	}
> +
> +	return sgt;
> +}
> +
> +
>  static struct sg_table *exynos_map_dmabuf(struct dma_buf_attachment
> *attach,
>  					enum dma_data_direction direction)
>  {
> @@ -64,6 +117,8 @@ static struct sg_table *exynos_map_dmabuf(struct
> dma_buf_attachment *attach,
>  	struct exynos_drm_gem_buf *buffer;
>  	struct sg_table *sgt;
>  	int ret;
> +	int size, n_pages;
> +	struct page **pages = NULL;
> 
>  	DRM_DEBUG_KMS("%s\n", __FILE__);
> 
> @@ -71,27 +126,37 @@ static struct sg_table *exynos_map_dmabuf(struct
> dma_buf_attachment *attach,
> 
>  	buffer = exynos_gem_obj->buffer;
> 
> -	/* TODO. consider physically non-continuous memory with IOMMU. */
> +	size = buffer->size;
> +	n_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
> 
> -	sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
> -	if (!sgt) {
> -		DRM_DEBUG_KMS("failed to allocate sg table.\n");
> -		return ERR_PTR(-ENOMEM);
> +	pages = kmalloc(n_pages * sizeof pages[0], GFP_KERNEL);
> +	if (!pages) {
> +		DRM_DEBUG_KMS("failed to alloc page table\n");
> +		return NULL;
>  	}
> 
> -	ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
> +	ret = dma_get_pages(attach->dev, buffer->kvaddr,
> +				buffer->dma_addr, pages, n_pages);
>  	if (ret < 0) {
> -		DRM_DEBUG_KMS("failed to allocate scatter list.\n");
> -		kfree(sgt);
> -		sgt = NULL;
> -		return ERR_PTR(-ENOMEM);
> +		DRM_DEBUG_KMS("failed to get buffer pages from DMA API\n");
> +		return NULL;
>  	}
> +	if (ret != n_pages) {
> +		DRM_DEBUG_KMS("failed to get all pages from DMA API\n");
> +		return NULL;
> +	}
> +
> +	sgt = drm_dc_pages_to_sgt(pages, n_pages, 0, 0, buffer->dma_addr);
> +	if (IS_ERR(sgt)) {
> +		DRM_DEBUG_KMS("failed to prepare sg table\n");
> +		return NULL;
> +	}
> +
> +	sgt->nents = dma_map_sg(attach->dev, sgt->sgl,
> +				sgt->orig_nents, DMA_BIDIRECTIONAL);
> 
> -	sg_init_table(sgt->sgl, 1);
> -	sg_dma_len(sgt->sgl) = buffer->size;
> -	sg_set_page(sgt->sgl, pfn_to_page(PFN_DOWN(buffer->dma_addr)),
> -			buffer->size, 0);
> -	sg_dma_address(sgt->sgl) = buffer->dma_addr;
> +	/* pages are no longer needed */
> +	kfree(pages);
> 
>  	/*
>  	 * increase reference count of this buffer.
> @@ -303,8 +368,6 @@ int exynos_dmabuf_prime_fd_to_handle(struct drm_device
> *drm_dev,
>  	if (ret < 0)
>  		goto fail_handle;
> 
> -	/* consider physically non-continuous memory with IOMMU. */
> -
>  	buffer->dma_addr = sg_dma_address(sgt->sgl);
>  	buffer->size = sg_dma_len(sgt->sgl);
> 
> @@ -316,6 +379,7 @@ int exynos_dmabuf_prime_fd_to_handle(struct drm_device
> *drm_dev,
>  	atomic_set(&buffer->shared_refcount, 1);
> 
>  	exynos_gem_obj->base.import_attach = attach;
> +	exynos_gem_obj->buffer = buffer;
> 
>  	ret = drm_prime_insert_fd_handle_mapping(&file_priv->prime,
>  							dmabuf, *handle);
> --
> 1.7.0.4



More information about the dri-devel mailing list