<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>