[PATCH v2] drm/exynos: use prime helpers

Inki Dae inki.dae at samsung.com
Thu Dec 6 22:36:33 PST 2012


Hi,

CCing media guys.

I agree with you but we should consider one issue released to v4l2.

As you may know, V4L2-based driver uses vb2 as buffer manager and the vb2
includes dmabuf feature>(import and export) And v4l2 uses streaming
concept>(qbuf and dqbuf)
With dmabuf and iommu, generally qbuf imports a fd into its own buffer and
maps it with its own iommu table calling dma_buf_map_attachment(). And
dqbuf calls dma_buf_unmap_attachment() to unmap that buffer from its own
iommu table.
But now vb2's unmap_dma_buf callback is nothing to do. I think that the
reason is the below issue,

If qbuf maps buffer with iomm table and dqbuf unmaps it from iommu table
then it has performance deterioration because qbuf and dqbuf are called
repeatedly.
And this means map/unmap are repeated also. So I think media guys moved
dma_unmap_sg call from its own unmap_dma_buf callback to detach callback
instead.
For this, you can refer to vb2_dc_dmabuf_ops_unmap and
vb2_dc_dmabuf_ops_detach function.

So I added the below patch to avoid that performance deterioration and am
testing it now.(this patch is derived from videobuf2-dma-contig.c)

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

Thus, I'm not sure that your common set could cover all the cases including
other frameworks. Please give me any opinions.

Thanks,
Inki Dae


2012/12/7 Aaron Plattner <aplattner at nvidia.com>

> Simplify the Exynos prime implementation by using the default behavior
> provided
> by drm_gem_prime_import and drm_gem_prime_export.
>
> Signed-off-by: Aaron Plattner <aplattner at nvidia.com>
> ---
> v2: fix dumb mistakes now that I have a toolchain that can compile-test
> this
>
>  drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | 156
> ++---------------------------
>  drivers/gpu/drm/exynos/exynos_drm_dmabuf.h |  13 ++-
>  drivers/gpu/drm/exynos/exynos_drm_drv.c    |   2 +
>  3 files changed, 20 insertions(+), 151 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
> b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
> index 539da9f..71b40f4 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
> @@ -28,8 +28,6 @@
>  #include "exynos_drm_drv.h"
>  #include "exynos_drm_gem.h"
>
> -#include <linux/dma-buf.h>
> -
>  static struct sg_table *exynos_get_sgt(struct drm_device *drm_dev,
>                                         struct exynos_drm_gem_buf *buf)
>  {
> @@ -56,15 +54,12 @@ out:
>         return NULL;
>  }
>
> -static struct sg_table *
> -               exynos_gem_map_dma_buf(struct dma_buf_attachment *attach,
> -                                       enum dma_data_direction dir)
> +struct sg_table *exynos_gem_prime_get_pages(struct drm_gem_object *obj)
>  {
> -       struct exynos_drm_gem_obj *gem_obj = attach->dmabuf->priv;
> +       struct exynos_drm_gem_obj *gem_obj = to_exynos_gem_obj(obj);
>         struct drm_device *dev = gem_obj->base.dev;
>         struct exynos_drm_gem_buf *buf;
>         struct sg_table *sgt = NULL;
> -       int nents;
>
>         DRM_DEBUG_PRIME("%s\n", __FILE__);
>
> @@ -74,120 +69,20 @@ static struct sg_table *
>                 return sgt;
>         }
>
> -       mutex_lock(&dev->struct_mutex);
> -
>         sgt = exynos_get_sgt(dev, buf);
>         if (!sgt)
> -               goto err_unlock;
> -
> -       nents = dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir);
> -       if (!nents) {
> -               DRM_ERROR("failed to map sgl with iommu.\n");
> -               sgt = NULL;
> -               goto err_unlock;
> -       }
> +               goto err;
>
>         DRM_DEBUG_PRIME("buffer size = 0x%lx\n", buf->size);
>
> -err_unlock:
> -       mutex_unlock(&dev->struct_mutex);
> +err:
>         return sgt;
>  }
>
> -static void exynos_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
> -                                               struct sg_table *sgt,
> -                                               enum dma_data_direction
> dir)
> -{
> -       dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);
> -
> -       sg_free_table(sgt);
> -       kfree(sgt);
> -       sgt = NULL;
> -}
> -
> -static void exynos_dmabuf_release(struct dma_buf *dmabuf)
> +struct drm_gem_object *exynos_gem_prime_import_sg(struct drm_device *dev,
> +                                                 size_t size,
> +                                                 struct sg_table *sgt)
>  {
> -       struct exynos_drm_gem_obj *exynos_gem_obj = dmabuf->priv;
> -
> -       DRM_DEBUG_PRIME("%s\n", __FILE__);
> -
> -       /*
> -        * exynos_dmabuf_release() call means that file object's
> -        * f_count is 0 and it calls drm_gem_object_handle_unreference()
> -        * to drop the references that these values had been increased
> -        * at drm_prime_handle_to_fd()
> -        */
> -       if (exynos_gem_obj->base.export_dma_buf == dmabuf) {
> -               exynos_gem_obj->base.export_dma_buf = NULL;
> -
> -               /*
> -                * drop this gem object refcount to release allocated
> buffer
> -                * and resources.
> -                */
> -               drm_gem_object_unreference_unlocked(&exynos_gem_obj->base);
> -       }
> -}
> -
> -static void *exynos_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf,
> -                                               unsigned long page_num)
> -{
> -       /* TODO */
> -
> -       return NULL;
> -}
> -
> -static void exynos_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf,
> -                                               unsigned long page_num,
> -                                               void *addr)
> -{
> -       /* TODO */
> -}
> -
> -static void *exynos_gem_dmabuf_kmap(struct dma_buf *dma_buf,
> -                                       unsigned long page_num)
> -{
> -       /* TODO */
> -
> -       return NULL;
> -}
> -
> -static void exynos_gem_dmabuf_kunmap(struct dma_buf *dma_buf,
> -                                       unsigned long page_num, void *addr)
> -{
> -       /* TODO */
> -}
> -
> -static int exynos_gem_dmabuf_mmap(struct dma_buf *dma_buf,
> -       struct vm_area_struct *vma)
> -{
> -       return -ENOTTY;
> -}
> -
> -static struct dma_buf_ops exynos_dmabuf_ops = {
> -       .map_dma_buf            = exynos_gem_map_dma_buf,
> -       .unmap_dma_buf          = exynos_gem_unmap_dma_buf,
> -       .kmap                   = exynos_gem_dmabuf_kmap,
> -       .kmap_atomic            = exynos_gem_dmabuf_kmap_atomic,
> -       .kunmap                 = exynos_gem_dmabuf_kunmap,
> -       .kunmap_atomic          = exynos_gem_dmabuf_kunmap_atomic,
> -       .mmap                   = exynos_gem_dmabuf_mmap,
> -       .release                = exynos_dmabuf_release,
> -};
> -
> -struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev,
> -                               struct drm_gem_object *obj, int flags)
> -{
> -       struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
> -
> -       return dma_buf_export(exynos_gem_obj, &exynos_dmabuf_ops,
> -                               exynos_gem_obj->base.size, 0600);
> -}
> -
> -struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device
> *drm_dev,
> -                               struct dma_buf *dma_buf)
> -{
> -       struct dma_buf_attachment *attach;
> -       struct sg_table *sgt;
>         struct scatterlist *sgl;
>         struct exynos_drm_gem_obj *exynos_gem_obj;
>         struct exynos_drm_gem_buf *buffer;
> @@ -195,39 +90,13 @@ struct drm_gem_object
> *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
>
>         DRM_DEBUG_PRIME("%s\n", __FILE__);
>
> -       /* is this one of own objects? */
> -       if (dma_buf->ops == &exynos_dmabuf_ops) {
> -               struct drm_gem_object *obj;
> -
> -               exynos_gem_obj = dma_buf->priv;
> -               obj = &exynos_gem_obj->base;
> -
> -               /* is it from our device? */
> -               if (obj->dev == drm_dev) {
> -                       drm_gem_object_reference(obj);
> -                       return obj;
> -               }
> -       }
> -
> -       attach = dma_buf_attach(dma_buf, drm_dev->dev);
> -       if (IS_ERR(attach))
> -               return ERR_PTR(-EINVAL);
> -
> -
> -       sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
> -       if (IS_ERR_OR_NULL(sgt)) {
> -               ret = PTR_ERR(sgt);
> -               goto err_buf_detach;
> -       }
> -
>         buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
>         if (!buffer) {
>                 DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n");
> -               ret = -ENOMEM;
> -               goto err_unmap_attach;
> +               return ERR_PTR(-ENOMEM);
>         }
>
> -       exynos_gem_obj = exynos_drm_gem_init(drm_dev, dma_buf->size);
> +       exynos_gem_obj = exynos_drm_gem_init(dev, size);
>         if (!exynos_gem_obj) {
>                 ret = -ENOMEM;
>                 goto err_free_buffer;
> @@ -235,7 +104,7 @@ struct drm_gem_object
> *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
>
>         sgl = sgt->sgl;
>
> -       buffer->size = dma_buf->size;
> +       buffer->size = size;
>         buffer->dma_addr = sg_dma_address(sgl);
>
>         if (sgt->nents == 1) {
> @@ -253,7 +122,6 @@ struct drm_gem_object
> *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
>
>         exynos_gem_obj->buffer = buffer;
>         buffer->sgt = sgt;
> -       exynos_gem_obj->base.import_attach = attach;
>
>         DRM_DEBUG_PRIME("dma_addr = 0x%x, size = 0x%lx\n",
> buffer->dma_addr,
>
> buffer->size);
> @@ -263,10 +131,6 @@ struct drm_gem_object
> *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
>  err_free_buffer:
>         kfree(buffer);
>         buffer = NULL;
> -err_unmap_attach:
> -       dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
> -err_buf_detach:
> -       dma_buf_detach(dma_buf, attach);
>         return ERR_PTR(ret);
>  }
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h
> b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h
> index 662a8f9..f198183 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h
> @@ -27,13 +27,16 @@
>  #define _EXYNOS_DRM_DMABUF_H_
>
>  #ifdef CONFIG_DRM_EXYNOS_DMABUF
> -struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev,
> -                               struct drm_gem_object *obj, int flags);
> -
> -struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device
> *drm_dev,
> -                                               struct dma_buf *dma_buf);
> +#define exynos_dmabuf_prime_export             drm_gem_prime_export
> +#define exynos_dmabuf_prime_import             drm_gem_prime_import
> +struct sg_table *exynos_gem_prime_get_pages(struct drm_gem_object *obj);
> +struct drm_gem_object *exynos_gem_prime_import_sg(struct drm_device *dev,
> +                                                 size_t size,
> +                                                 struct sg_table *sg);
>  #else
>  #define exynos_dmabuf_prime_export             NULL
>  #define exynos_dmabuf_prime_import             NULL
> +#define exynos_gem_prime_get_pages             NULL
> +#define exynos_gem_prime_import_sg             NULL
>  #endif
>  #endif
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c
> b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> index 2b287d2..2a04e97 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> @@ -283,6 +283,8 @@ static struct drm_driver exynos_drm_driver = {
>         .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
>         .gem_prime_export       = exynos_dmabuf_prime_export,
>         .gem_prime_import       = exynos_dmabuf_prime_import,
> +       .gem_prime_get_pages    = exynos_gem_prime_get_pages,
> +       .gem_prime_import_sg    = exynos_gem_prime_import_sg,
>         .ioctls                 = exynos_ioctls,
>         .fops                   = &exynos_drm_driver_fops,
>         .name   = DRIVER_NAME,
> --
> 1.8.0.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20121207/cb11826c/attachment-0001.html>


More information about the dri-devel mailing list