diff mbox

[v2] drm/exynos: create new sgt from existing sgt

Message ID 1354518044-31990-1-git-send-email-prathyush.k@samsung.com (mailing list archive)
State New, archived
Headers show

Commit Message

Prathyush K Dec. 3, 2012, 7 a.m. UTC
Changelog v2:

Implement copy sgt code in exynos_get_sgt itself instead of calling
sg_clone_table.

Changelog v1:

During map_dma_buf, a new sgt needs to be created before being mapped to
another device's address space. Currently, this sgt is created by calling
dma_get_sgtable which creates a sgt from pages. This will be time consuming
if the map/unmap calls are done repeatedly for very large buffers.

Instead, we can just use the sgt which was already created during
buffer allocation and create the new sgt by copying the sgls from the
existing sgt.

And this patch is based on exynos-drm-next-iommu branch of
git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos

Signed-off-by: Prathyush K <prathyush.k@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_dmabuf.c |   18 +++++++++++++++---
 1 files changed, 15 insertions(+), 3 deletions(-)

Comments

Inki Dae Dec. 4, 2012, 5:16 a.m. UTC | #1
2012/12/3 Prathyush K <prathyush.k@samsung.com>

> Changelog v2:
>
> Implement copy sgt code in exynos_get_sgt itself instead of calling
> sg_clone_table.
>
>
Now we are working on dmabuf feature update that adds attach and detach
callbacks and with this patch, exynos_get_sgt function will be removed.
For this, please refer to the below link,

http://git.kernel.org/?p=linux/kernel/git/daeinki/drm-exynos.git;a=commit;h=a9626efd74cb9133d31f4f42e16a59d3e2cfb03e

And this patch would resolve the performance deterioration to v4l2's
streaming service.
The performance issue are induced when v4l2's qbuf and dqbuf are called
repeatedly with gem buffer imported.(dmabuf fd -> vb2 buffer)
So unmapping would be done by dma_buf_detach instead of
dma_buf_unmap_attachment.
For this, we are testing it and if works fine then this patch will be
posted.


> Changelog v1:
>
> During map_dma_buf, a new sgt needs to be created before being mapped to
> another device's address space. Currently, this sgt is created by calling
> dma_get_sgtable which creates a sgt from pages. This will be time consuming
> if the map/unmap calls are done repeatedly for very large buffers.
>
> Instead, we can just use the sgt which was already created during
> buffer allocation and create the new sgt by copying the sgls from the
> existing sgt.
>
> And this patch is based on exynos-drm-next-iommu branch of
> git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos
>
> Signed-off-by: Prathyush K <prathyush.k@samsung.com>
> ---
>  drivers/gpu/drm/exynos/exynos_drm_dmabuf.c |   18 +++++++++++++++---
>  1 files changed, 15 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
> b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
> index d9307bd..91c7db1 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
> @@ -34,19 +34,31 @@ static struct sg_table *exynos_get_sgt(struct
> drm_device *drm_dev,
>                                         struct exynos_drm_gem_buf *buf)
>  {
>         struct sg_table *sgt = NULL;
> +       struct scatterlist *s, *s_out;
> +       unsigned int i;
>         int ret;
>
> +       if (!buf->sgt) {
> +               DRM_ERROR("no sg table.\n");
> +               goto out;
> +       }
> +
>         sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
>         if (!sgt)
>                 goto out;
>
> -       ret = dma_get_sgtable(drm_dev->dev, sgt, buf->kvaddr,
> -                               buf->dma_addr, buf->size);
> +       ret = sg_alloc_table(sgt, buf->sgt->orig_nents, GFP_KERNEL);
>         if (ret < 0) {
> -               DRM_ERROR("failed to get sgtable.\n");
> +               DRM_ERROR("failed to alloc table\n");
>                 goto err_free_sgt;
>         }
>
> +       s_out = sgt->sgl;
> +       for_each_sg(buf->sgt->sgl, s, buf->sgt->orig_nents, i) {
> +               sg_set_page(s_out, sg_page(s), s->length, s->offset);
> +               s_out = sg_next(s_out);
> +       }
> +
>         return sgt;
>
>  err_free_sgt:
> --
> 1.7.0.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>
diff mbox

Patch

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
index d9307bd..91c7db1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
@@ -34,19 +34,31 @@  static struct sg_table *exynos_get_sgt(struct drm_device *drm_dev,
 					struct exynos_drm_gem_buf *buf)
 {
 	struct sg_table *sgt = NULL;
+	struct scatterlist *s, *s_out;
+	unsigned int i;
 	int ret;
 
+	if (!buf->sgt) {
+		DRM_ERROR("no sg table.\n");
+		goto out;
+	}
+
 	sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
 	if (!sgt)
 		goto out;
 
-	ret = dma_get_sgtable(drm_dev->dev, sgt, buf->kvaddr,
-				buf->dma_addr, buf->size);
+	ret = sg_alloc_table(sgt, buf->sgt->orig_nents, GFP_KERNEL);
 	if (ret < 0) {
-		DRM_ERROR("failed to get sgtable.\n");
+		DRM_ERROR("failed to alloc table\n");
 		goto err_free_sgt;
 	}
 
+	s_out = sgt->sgl;
+	for_each_sg(buf->sgt->sgl, s, buf->sgt->orig_nents, i) {
+		sg_set_page(s_out, sg_page(s), s->length, s->offset);
+		s_out = sg_next(s_out);
+	}
+
 	return sgt;
 
 err_free_sgt: