[PATCH v4] drm/exynos: add iommu support for exynos drm framework

2012-11-05 Thread Inki Dae
Changelog v4:
- fix condition to drm_iommu_detach_device funtion.

Changelog v3:
- add dma_parms->max_segment_size setting of drm_device->dev.
- use devm_kzalloc instead of kzalloc.

Changelog v2:
- fix iommu attach condition.
  . check archdata.dma_ops of drm device instead of
subdrv device's one.
- code clean to exynos_drm_iommu.c file.
  . remove '#ifdef CONFIG_ARM_DMA_USE_IOMMU' from exynos_drm_iommu.c
and add it to driver/gpu/drm/exynos/Kconfig.

Changelog v1:
This patch adds iommu support for exynos drm framework with dma mapping
api. In this patch, we used dma mapping api to allocate physical memory
and maps it with iommu table and removed some existing codes and added
new some codes for iommu support.

GEM allocation requires one device object to use dma mapping api so
this patch uses one iommu mapping for all sub drivers. In other words,
all sub drivers have same iommu mapping.

Signed-off-by: Inki Dae 
Signed-off-by: Kyungmin Park 
---
 drivers/gpu/drm/exynos/Kconfig |6 +
 drivers/gpu/drm/exynos/Makefile|1 +
 drivers/gpu/drm/exynos/exynos_drm_buf.c|   88 +
 drivers/gpu/drm/exynos/exynos_drm_dmabuf.c |   87 +---
 drivers/gpu/drm/exynos/exynos_drm_drv.c|   23 +++-
 drivers/gpu/drm/exynos/exynos_drm_drv.h|   11 ++
 drivers/gpu/drm/exynos/exynos_drm_fb.c |   52 +++-
 drivers/gpu/drm/exynos/exynos_drm_gem.c|  210 ++--
 drivers/gpu/drm/exynos/exynos_drm_gem.h|1 +
 drivers/gpu/drm/exynos/exynos_drm_iommu.c  |  150 
 drivers/gpu/drm/exynos/exynos_drm_iommu.h  |   85 +++
 11 files changed, 409 insertions(+), 305 deletions(-)
 create mode 100644 drivers/gpu/drm/exynos/exynos_drm_iommu.c
 create mode 100644 drivers/gpu/drm/exynos/exynos_drm_iommu.h

diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 59a26e5..4ea8cdc 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -10,6 +10,12 @@ config DRM_EXYNOS
  Choose this option if you have a Samsung SoC EXYNOS chipset.
  If M is selected the module will be called exynosdrm.

+config DRM_EXYNOS_IOMMU
+   bool "EXYNOS DRM IOMMU Support"
+   depends on DRM_EXYNOS && EXYNOS_IOMMU && ARM_DMA_USE_IOMMU
+   help
+ Choose this option if you want to use IOMMU feature for DRM.
+
 config DRM_EXYNOS_DMABUF
bool "EXYNOS DRM DMABUF"
depends on DRM_EXYNOS
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index eb651ca..26813b8 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -8,6 +8,7 @@ exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o 
exynos_drm_connector.o \
exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o \
exynos_drm_plane.o

+exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD)+= exynos_drm_fimd.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)+= exynos_hdmi.o exynos_mixer.o \
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c 
b/drivers/gpu/drm/exynos/exynos_drm_buf.c
index 118c117..48c5896 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_buf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c
@@ -33,71 +33,58 @@
 static int lowlevel_buffer_allocate(struct drm_device *dev,
unsigned int flags, struct exynos_drm_gem_buf *buf)
 {
-   dma_addr_t start_addr;
+   int ret = 0;
unsigned int npages, i = 0;
struct scatterlist *sgl;
-   int ret = 0;
+   enum dma_attr attr = DMA_ATTR_FORCE_CONTIGUOUS;

DRM_DEBUG_KMS("%s\n", __FILE__);

-   if (IS_NONCONTIG_BUFFER(flags)) {
-   DRM_DEBUG_KMS("not support allocation type.\n");
-   return -EINVAL;
-   }
-
if (buf->dma_addr) {
DRM_DEBUG_KMS("already allocated.\n");
return 0;
}

-   if (buf->size >= SZ_1M) {
-   npages = buf->size >> SECTION_SHIFT;
-   buf->page_size = SECTION_SIZE;
-   } else if (buf->size >= SZ_64K) {
-   npages = buf->size >> 16;
-   buf->page_size = SZ_64K;
-   } else {
-   npages = buf->size >> PAGE_SHIFT;
-   buf->page_size = PAGE_SIZE;
+   init_dma_attrs(>dma_attrs);
+
+   if (flags & EXYNOS_BO_NONCONTIG)
+   attr = DMA_ATTR_WRITE_COMBINE;
+
+   dma_set_attr(attr, >dma_attrs);
+
+   buf->kvaddr = dma_alloc_attrs(dev->dev, buf->size,
+   >dma_addr, GFP_KERNEL, >dma_attrs);
+   if (!buf->kvaddr) {
+   DRM_ERROR("failed to allocate buffer.\n");
+   return -ENOMEM;
}

buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
if (!buf->sgt) {
DRM_ERROR("failed to allocate sg table.\n");
-   return -ENOMEM;
+   

[PATCH v4] drm/exynos: add iommu support for exynos drm framework

2012-11-04 Thread Inki Dae
Changelog v4:
- fix condition to drm_iommu_detach_device funtion.

Changelog v3:
- add dma_parms-max_segment_size setting of drm_device-dev.
- use devm_kzalloc instead of kzalloc.

Changelog v2:
- fix iommu attach condition.
  . check archdata.dma_ops of drm device instead of
subdrv device's one.
- code clean to exynos_drm_iommu.c file.
  . remove '#ifdef CONFIG_ARM_DMA_USE_IOMMU' from exynos_drm_iommu.c
and add it to driver/gpu/drm/exynos/Kconfig.

Changelog v1:
This patch adds iommu support for exynos drm framework with dma mapping
api. In this patch, we used dma mapping api to allocate physical memory
and maps it with iommu table and removed some existing codes and added
new some codes for iommu support.

GEM allocation requires one device object to use dma mapping api so
this patch uses one iommu mapping for all sub drivers. In other words,
all sub drivers have same iommu mapping.

Signed-off-by: Inki Dae inki@samsung.com
Signed-off-by: Kyungmin Park kyungmin.p...@samsung.com
---
 drivers/gpu/drm/exynos/Kconfig |6 +
 drivers/gpu/drm/exynos/Makefile|1 +
 drivers/gpu/drm/exynos/exynos_drm_buf.c|   88 +
 drivers/gpu/drm/exynos/exynos_drm_dmabuf.c |   87 +---
 drivers/gpu/drm/exynos/exynos_drm_drv.c|   23 +++-
 drivers/gpu/drm/exynos/exynos_drm_drv.h|   11 ++
 drivers/gpu/drm/exynos/exynos_drm_fb.c |   52 +++-
 drivers/gpu/drm/exynos/exynos_drm_gem.c|  210 ++--
 drivers/gpu/drm/exynos/exynos_drm_gem.h|1 +
 drivers/gpu/drm/exynos/exynos_drm_iommu.c  |  150 
 drivers/gpu/drm/exynos/exynos_drm_iommu.h  |   85 +++
 11 files changed, 409 insertions(+), 305 deletions(-)
 create mode 100644 drivers/gpu/drm/exynos/exynos_drm_iommu.c
 create mode 100644 drivers/gpu/drm/exynos/exynos_drm_iommu.h

diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 59a26e5..4ea8cdc 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -10,6 +10,12 @@ config DRM_EXYNOS
  Choose this option if you have a Samsung SoC EXYNOS chipset.
  If M is selected the module will be called exynosdrm.
 
+config DRM_EXYNOS_IOMMU
+   bool EXYNOS DRM IOMMU Support
+   depends on DRM_EXYNOS  EXYNOS_IOMMU  ARM_DMA_USE_IOMMU
+   help
+ Choose this option if you want to use IOMMU feature for DRM.
+
 config DRM_EXYNOS_DMABUF
bool EXYNOS DRM DMABUF
depends on DRM_EXYNOS
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index eb651ca..26813b8 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -8,6 +8,7 @@ exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o 
exynos_drm_connector.o \
exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o \
exynos_drm_plane.o
 
+exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD)+= exynos_drm_fimd.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)+= exynos_hdmi.o exynos_mixer.o \
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c 
b/drivers/gpu/drm/exynos/exynos_drm_buf.c
index 118c117..48c5896 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_buf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c
@@ -33,71 +33,58 @@
 static int lowlevel_buffer_allocate(struct drm_device *dev,
unsigned int flags, struct exynos_drm_gem_buf *buf)
 {
-   dma_addr_t start_addr;
+   int ret = 0;
unsigned int npages, i = 0;
struct scatterlist *sgl;
-   int ret = 0;
+   enum dma_attr attr = DMA_ATTR_FORCE_CONTIGUOUS;
 
DRM_DEBUG_KMS(%s\n, __FILE__);
 
-   if (IS_NONCONTIG_BUFFER(flags)) {
-   DRM_DEBUG_KMS(not support allocation type.\n);
-   return -EINVAL;
-   }
-
if (buf-dma_addr) {
DRM_DEBUG_KMS(already allocated.\n);
return 0;
}
 
-   if (buf-size = SZ_1M) {
-   npages = buf-size  SECTION_SHIFT;
-   buf-page_size = SECTION_SIZE;
-   } else if (buf-size = SZ_64K) {
-   npages = buf-size  16;
-   buf-page_size = SZ_64K;
-   } else {
-   npages = buf-size  PAGE_SHIFT;
-   buf-page_size = PAGE_SIZE;
+   init_dma_attrs(buf-dma_attrs);
+
+   if (flags  EXYNOS_BO_NONCONTIG)
+   attr = DMA_ATTR_WRITE_COMBINE;
+
+   dma_set_attr(attr, buf-dma_attrs);
+
+   buf-kvaddr = dma_alloc_attrs(dev-dev, buf-size,
+   buf-dma_addr, GFP_KERNEL, buf-dma_attrs);
+   if (!buf-kvaddr) {
+   DRM_ERROR(failed to allocate buffer.\n);
+   return -ENOMEM;
}
 
buf-sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
if (!buf-sgt) {
DRM_ERROR(failed to allocate sg table.\n);
-   return -ENOMEM;