<br>Hi,<br><br>CCing media guys.<br><br>I agree with you but we should consider one issue released to v4l2.<br><br>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)<br>
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.<br>
But now vb2's unmap_dma_buf callback is nothing to do. I think that the reason is the below issue,<br><br>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.<br>
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.<br>For this, you can refer to vb2_dc_dmabuf_ops_unmap and vb2_dc_dmabuf_ops_detach function.<br>
<br>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) <br>        <a href="http://git.kernel.org/?p=linux/kernel/git/daeinki/drm-exynos.git;a=commit;h=576b1c3de8b90cf1570b8418b60afd1edaae4e30">http://git.kernel.org/?p=linux/kernel/git/daeinki/drm-exynos.git;a=commit;h=576b1c3de8b90cf1570b8418b60afd1edaae4e30</a><br>
<br>Thus, I'm not sure that your common set could cover all the cases including other frameworks. Please give me any opinions.<br><br>Thanks,<br>Inki Dae<br><br><br><div class="gmail_quote">2012/12/7 Aaron Plattner <span dir="ltr"><<a href="mailto:aplattner@nvidia.com" target="_blank">aplattner@nvidia.com</a>></span><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">Simplify the Exynos prime implementation by using the default behavior provided<br>
by drm_gem_prime_import and drm_gem_prime_export.<br>
<br>
Signed-off-by: Aaron Plattner <<a href="mailto:aplattner@nvidia.com">aplattner@nvidia.com</a>><br>
---<br>
</div>v2: fix dumb mistakes now that I have a toolchain that can compile-test this<br>
<br>
 drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | 156 ++---------------------------<br>
<div class="im"> drivers/gpu/drm/exynos/exynos_drm_dmabuf.h |  13 ++-<br>
 drivers/gpu/drm/exynos/exynos_drm_drv.c    |   2 +<br>
</div> 3 files changed, 20 insertions(+), 151 deletions(-)<br>
<br>
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c<br>
index 539da9f..71b40f4 100644<br>
<div class="im">--- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c<br>
+++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c<br>
@@ -28,8 +28,6 @@<br>
 #include "exynos_drm_drv.h"<br>
 #include "exynos_drm_gem.h"<br>
<br>
-#include <linux/dma-buf.h><br>
-<br>
 static struct sg_table *exynos_get_sgt(struct drm_device *drm_dev,<br>
                                        struct exynos_drm_gem_buf *buf)<br>
 {<br>
@@ -56,15 +54,12 @@ out:<br>
        return NULL;<br>
 }<br>
<br>
-static struct sg_table *<br>
-               exynos_gem_map_dma_buf(struct dma_buf_attachment *attach,<br>
-                                       enum dma_data_direction dir)<br>
+struct sg_table *exynos_gem_prime_get_pages(struct drm_gem_object *obj)<br>
 {<br>
-       struct exynos_drm_gem_obj *gem_obj = attach->dmabuf->priv;<br>
+       struct exynos_drm_gem_obj *gem_obj = to_exynos_gem_obj(obj);<br>
        struct drm_device *dev = gem_obj->base.dev;<br>
        struct exynos_drm_gem_buf *buf;<br>
        struct sg_table *sgt = NULL;<br>
-       int nents;<br>
<br>
        DRM_DEBUG_PRIME("%s\n", __FILE__);<br>
<br>
</div>@@ -74,120 +69,20 @@ static struct sg_table *<br>
<div><div class="h5">                return sgt;<br>
        }<br>
<br>
-       mutex_lock(&dev->struct_mutex);<br>
-<br>
        sgt = exynos_get_sgt(dev, buf);<br>
        if (!sgt)<br>
-               goto err_unlock;<br>
-<br>
-       nents = dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir);<br>
-       if (!nents) {<br>
-               DRM_ERROR("failed to map sgl with iommu.\n");<br>
-               sgt = NULL;<br>
-               goto err_unlock;<br>
-       }<br>
+               goto err;<br>
<br>
        DRM_DEBUG_PRIME("buffer size = 0x%lx\n", buf->size);<br>
<br>
-err_unlock:<br>
-       mutex_unlock(&dev->struct_mutex);<br>
+err:<br>
        return sgt;<br>
 }<br>
<br>
-static void exynos_gem_unmap_dma_buf(struct dma_buf_attachment *attach,<br>
-                                               struct sg_table *sgt,<br>
-                                               enum dma_data_direction dir)<br>
-{<br>
-       dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);<br>
-<br>
-       sg_free_table(sgt);<br>
-       kfree(sgt);<br>
-       sgt = NULL;<br>
-}<br>
-<br>
-static void exynos_dmabuf_release(struct dma_buf *dmabuf)<br>
+struct drm_gem_object *exynos_gem_prime_import_sg(struct drm_device *dev,<br>
+                                                 size_t size,<br>
</div></div>+                                                 struct sg_table *sgt)<br>
<div><div class="h5"> {<br>
-       struct exynos_drm_gem_obj *exynos_gem_obj = dmabuf->priv;<br>
-<br>
-       DRM_DEBUG_PRIME("%s\n", __FILE__);<br>
-<br>
-       /*<br>
-        * exynos_dmabuf_release() call means that file object's<br>
-        * f_count is 0 and it calls drm_gem_object_handle_unreference()<br>
-        * to drop the references that these values had been increased<br>
-        * at drm_prime_handle_to_fd()<br>
-        */<br>
-       if (exynos_gem_obj->base.export_dma_buf == dmabuf) {<br>
-               exynos_gem_obj->base.export_dma_buf = NULL;<br>
-<br>
-               /*<br>
-                * drop this gem object refcount to release allocated buffer<br>
-                * and resources.<br>
-                */<br>
-               drm_gem_object_unreference_unlocked(&exynos_gem_obj->base);<br>
-       }<br>
-}<br>
-<br>
-static void *exynos_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf,<br>
-                                               unsigned long page_num)<br>
-{<br>
-       /* TODO */<br>
-<br>
-       return NULL;<br>
-}<br>
-<br>
-static void exynos_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf,<br>
-                                               unsigned long page_num,<br>
-                                               void *addr)<br>
-{<br>
-       /* TODO */<br>
-}<br>
-<br>
-static void *exynos_gem_dmabuf_kmap(struct dma_buf *dma_buf,<br>
-                                       unsigned long page_num)<br>
-{<br>
-       /* TODO */<br>
-<br>
-       return NULL;<br>
-}<br>
-<br>
-static void exynos_gem_dmabuf_kunmap(struct dma_buf *dma_buf,<br>
-                                       unsigned long page_num, void *addr)<br>
-{<br>
-       /* TODO */<br>
-}<br>
-<br>
-static int exynos_gem_dmabuf_mmap(struct dma_buf *dma_buf,<br>
-       struct vm_area_struct *vma)<br>
-{<br>
-       return -ENOTTY;<br>
-}<br>
-<br>
-static struct dma_buf_ops exynos_dmabuf_ops = {<br>
-       .map_dma_buf            = exynos_gem_map_dma_buf,<br>
-       .unmap_dma_buf          = exynos_gem_unmap_dma_buf,<br>
-       .kmap                   = exynos_gem_dmabuf_kmap,<br>
-       .kmap_atomic            = exynos_gem_dmabuf_kmap_atomic,<br>
-       .kunmap                 = exynos_gem_dmabuf_kunmap,<br>
-       .kunmap_atomic          = exynos_gem_dmabuf_kunmap_atomic,<br>
-       .mmap                   = exynos_gem_dmabuf_mmap,<br>
-       .release                = exynos_dmabuf_release,<br>
-};<br>
-<br>
-struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev,<br>
-                               struct drm_gem_object *obj, int flags)<br>
-{<br>
-       struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);<br>
-<br>
-       return dma_buf_export(exynos_gem_obj, &exynos_dmabuf_ops,<br>
-                               exynos_gem_obj->base.size, 0600);<br>
-}<br>
-<br>
-struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,<br>
-                               struct dma_buf *dma_buf)<br>
-{<br>
-       struct dma_buf_attachment *attach;<br>
</div></div>-       struct sg_table *sgt;<br>
<div class="im">        struct scatterlist *sgl;<br>
        struct exynos_drm_gem_obj *exynos_gem_obj;<br>
</div>        struct exynos_drm_gem_buf *buffer;<br>
@@ -195,39 +90,13 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,<br>
<div><div class="h5"><br>
        DRM_DEBUG_PRIME("%s\n", __FILE__);<br>
<br>
-       /* is this one of own objects? */<br>
-       if (dma_buf->ops == &exynos_dmabuf_ops) {<br>
-               struct drm_gem_object *obj;<br>
-<br>
-               exynos_gem_obj = dma_buf->priv;<br>
-               obj = &exynos_gem_obj->base;<br>
-<br>
-               /* is it from our device? */<br>
-               if (obj->dev == drm_dev) {<br>
-                       drm_gem_object_reference(obj);<br>
-                       return obj;<br>
-               }<br>
-       }<br>
-<br>
-       attach = dma_buf_attach(dma_buf, drm_dev->dev);<br>
-       if (IS_ERR(attach))<br>
-               return ERR_PTR(-EINVAL);<br>
-<br>
-<br>
-       sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);<br>
-       if (IS_ERR_OR_NULL(sgt)) {<br>
-               ret = PTR_ERR(sgt);<br>
-               goto err_buf_detach;<br>
-       }<br>
-<br>
        buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);<br>
        if (!buffer) {<br>
                DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n");<br>
-               ret = -ENOMEM;<br>
-               goto err_unmap_attach;<br>
+               return ERR_PTR(-ENOMEM);<br>
        }<br>
<br>
</div></div>-       exynos_gem_obj = exynos_drm_gem_init(drm_dev, dma_buf->size);<br>
+       exynos_gem_obj = exynos_drm_gem_init(dev, size);<br>
        if (!exynos_gem_obj) {<br>
                ret = -ENOMEM;<br>
                goto err_free_buffer;<br>
@@ -235,7 +104,7 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,<br>
<br>
        sgl = sgt->sgl;<br>
<br>
-       buffer->size = dma_buf->size;<br>
+       buffer->size = size;<br>
        buffer->dma_addr = sg_dma_address(sgl);<br>
<br>
        if (sgt->nents == 1) {<br>
@@ -253,7 +122,6 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,<br>
<div class="im"><br>
        exynos_gem_obj->buffer = buffer;<br>
        buffer->sgt = sgt;<br>
-       exynos_gem_obj->base.import_attach = attach;<br>
<br>
        DRM_DEBUG_PRIME("dma_addr = 0x%x, size = 0x%lx\n", buffer->dma_addr,<br>
                                                                buffer->size);<br>
</div>@@ -263,10 +131,6 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,<br>
<div class="HOEnZb"><div class="h5"> err_free_buffer:<br>
        kfree(buffer);<br>
        buffer = NULL;<br>
-err_unmap_attach:<br>
-       dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);<br>
-err_buf_detach:<br>
-       dma_buf_detach(dma_buf, attach);<br>
        return ERR_PTR(ret);<br>
 }<br>
<br>
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h<br>
index 662a8f9..f198183 100644<br>
--- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h<br>
+++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h<br>
@@ -27,13 +27,16 @@<br>
 #define _EXYNOS_DRM_DMABUF_H_<br>
<br>
 #ifdef CONFIG_DRM_EXYNOS_DMABUF<br>
-struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev,<br>
-                               struct drm_gem_object *obj, int flags);<br>
-<br>
-struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,<br>
-                                               struct dma_buf *dma_buf);<br>
+#define exynos_dmabuf_prime_export             drm_gem_prime_export<br>
+#define exynos_dmabuf_prime_import             drm_gem_prime_import<br>
+struct sg_table *exynos_gem_prime_get_pages(struct drm_gem_object *obj);<br>
+struct drm_gem_object *exynos_gem_prime_import_sg(struct drm_device *dev,<br>
+                                                 size_t size,<br>
+                                                 struct sg_table *sg);<br>
 #else<br>
 #define exynos_dmabuf_prime_export             NULL<br>
 #define exynos_dmabuf_prime_import             NULL<br>
+#define exynos_gem_prime_get_pages             NULL<br>
+#define exynos_gem_prime_import_sg             NULL<br>
 #endif<br>
 #endif<br>
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c<br>
index 2b287d2..2a04e97 100644<br>
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c<br>
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c<br>
@@ -283,6 +283,8 @@ static struct drm_driver exynos_drm_driver = {<br>
        .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,<br>
        .gem_prime_export       = exynos_dmabuf_prime_export,<br>
        .gem_prime_import       = exynos_dmabuf_prime_import,<br>
+       .gem_prime_get_pages    = exynos_gem_prime_get_pages,<br>
+       .gem_prime_import_sg    = exynos_gem_prime_import_sg,<br>
        .ioctls                 = exynos_ioctls,<br>
        .fops                   = &exynos_drm_driver_fops,<br>
        .name   = DRIVER_NAME,<br>
--<br>
1.8.0.1<br>
<br>
_______________________________________________<br>
dri-devel mailing list<br>
<a href="mailto:dri-devel@lists.freedesktop.org">dri-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/dri-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/dri-devel</a><br>
</div></div></blockquote></div><br>