diff mbox

[v2] drm/exynos: use prime helpers

Message ID 1354819712-7019-1-git-send-email-aplattner@nvidia.com (mailing list archive)
State New, archived
Headers show

Commit Message

Aaron Plattner Dec. 6, 2012, 6:48 p.m. UTC
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@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(-)

Comments

Inki Dae Dec. 7, 2012, 6:36 a.m. UTC | #1
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@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@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@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>
Daniel Vetter Dec. 7, 2012, 8:11 a.m. UTC | #2
On Fri, Dec 7, 2012 at 7:36 AM, Inki Dae <inki.dae@samsung.com> wrote:
> Thus, I'm not sure that your common set could cover all the cases including
> other frameworks. Please give me any opinions.

I don't think that's required - as long as it is fairly useable by
many drivers a helper library is good enough. And since it's no
midlayer there's no requirement to use it, you're always free to do
your own special sauce in your driver. But I think the current rfc
could be made a bit more flexible so that more drivers could use at
least parts of it, see my other mail.
-Daniel
Aaron Plattner Dec. 7, 2012, 5:48 p.m. UTC | #3
On 12/06/2012 10:36 PM, Inki Dae wrote:
>
> 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.

It seems like this adjustment would make perfect sense to add to the 
helper layer I suggested.  E.g., instead of having an exynos_attach 
structure that caches the sgt, there'd be a struct drm_gem_prime_attach 
that would do the same thing, and save the sgt it gets from 
driver->gem_prime_get_sg.  Then it would benefit nouveau and radeon, too.

Alternatively, patch #4 could be dropped and Exynos can continue to 
reimplement all of this core functionality, since the helpers are 
optional, but I don't see anything about this change that should make it 
Exynos-specific, unless I'm missing something.

--
Aaron
Inki Dae Dec. 10, 2012, 4:33 a.m. UTC | #4
2012/12/8 Aaron Plattner <aplattner@nvidia.com>

> On 12/06/2012 10:36 PM, Inki Dae wrote:
>
>>
>> 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=**576b1c3de8b90cf1570b8418b60afd**1edaae4e30<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.
>>
>
> It seems like this adjustment would make perfect sense to add to the
> helper layer I suggested.  E.g., instead of having an exynos_attach
> structure that caches the sgt, there'd be a struct drm_gem_prime_attach
> that would do the same thing, and save the sgt it gets from
> driver->gem_prime_get_sg.  Then it would benefit nouveau and radeon, too.
>

If this change is applied to common helper and also that could be accepted
by other maintainers then I think it's better to use this common helper
instead of specific one.


>
> Alternatively, patch #4 could be dropped and Exynos can continue to
> reimplement all of this core functionality, since the helpers are optional,
> but I don't see anything about this change that should make it
> Exynos-specific,


I agree with you. I also think this change isn't specific to Exynos. But
you need to check if this is a reasonable change for other drivers also.

Thanks,
Inki Dae


> unless I'm missing something.
>
>
--
> Aaron
>
> ______________________________**_________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.**org <dri-devel@lists.freedesktop.org>
> http://lists.freedesktop.org/**mailman/listinfo/dri-devel<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 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,