Re: [PATCH v2] drm/exynos: use prime helpers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




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@xxxxxxxxxx>
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@xxxxxxxxxx>
---
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@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/dri-devel

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/dri-devel

[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux