[PATCHv6 2/7] ARM: dma-mapping: use asm-generic/dma-mapping-common.h

2012-02-10 Thread Marek Szyprowski
This patch modifies dma-mapping implementation on ARM architecture to
use common dma_map_ops structure and asm-generic/dma-mapping-common.h
helpers.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
Signed-off-by: Kyungmin Park kyungmin.p...@samsung.com
---
 arch/arm/Kconfig   |1 +
 arch/arm/include/asm/device.h  |1 +
 arch/arm/include/asm/dma-mapping.h |  197 +---
 arch/arm/mm/dma-mapping.c  |  149 ---
 4 files changed, 117 insertions(+), 231 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a48aecc..59102fb 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -4,6 +4,7 @@ config ARM
select HAVE_AOUT
select HAVE_DMA_API_DEBUG
select HAVE_IDE if PCI || ISA || PCMCIA
+   select HAVE_DMA_ATTRS
select HAVE_MEMBLOCK
select RTC_LIB
select SYS_SUPPORTS_APM_EMULATION
diff --git a/arch/arm/include/asm/device.h b/arch/arm/include/asm/device.h
index 7aa3680..6e2cb0e 100644
--- a/arch/arm/include/asm/device.h
+++ b/arch/arm/include/asm/device.h
@@ -7,6 +7,7 @@
 #define ASMARM_DEVICE_H
 
 struct dev_archdata {
+   struct dma_map_ops  *dma_ops;
 #ifdef CONFIG_DMABOUNCE
struct dmabounce_device_info *dmabounce;
 #endif
diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index 6bc056c..cf7b77c 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -10,6 +10,28 @@
 #include asm-generic/dma-coherent.h
 #include asm/memory.h
 
+extern struct dma_map_ops arm_dma_ops;
+
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+   if (dev  dev-archdata.dma_ops)
+   return dev-archdata.dma_ops;
+   return arm_dma_ops;
+}
+
+static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
+{
+   BUG_ON(!dev);
+   dev-archdata.dma_ops = ops;
+}
+
+#include asm-generic/dma-mapping-common.h
+
+static inline int dma_set_mask(struct device *dev, u64 mask)
+{
+   return get_dma_ops(dev)-set_dma_mask(dev, mask);
+}
+
 #ifdef __arch_page_to_dma
 #error Please update to __arch_pfn_to_dma
 #endif
@@ -117,7 +139,6 @@ static inline void __dma_page_dev_to_cpu(struct page *page, 
unsigned long off,
 
 extern int dma_supported(struct device *, u64);
 extern int dma_set_mask(struct device *, u64);
-
 /*
  * DMA errors are defined by all-bits-set in the DMA address.
  */
@@ -295,179 +316,17 @@ static inline void __dma_unmap_page(struct device *dev, 
dma_addr_t handle,
 }
 #endif /* CONFIG_DMABOUNCE */
 
-/**
- * dma_map_single - map a single buffer for streaming DMA
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @cpu_addr: CPU direct mapped address of buffer
- * @size: size of buffer to map
- * @dir: DMA transfer direction
- *
- * Ensure that any data held in the cache is appropriately discarded
- * or written back.
- *
- * The device owns this memory once this call has completed.  The CPU
- * can regain ownership by calling dma_unmap_single() or
- * dma_sync_single_for_cpu().
- */
-static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
-   size_t size, enum dma_data_direction dir)
-{
-   unsigned long offset;
-   struct page *page;
-   dma_addr_t addr;
-
-   BUG_ON(!virt_addr_valid(cpu_addr));
-   BUG_ON(!virt_addr_valid(cpu_addr + size - 1));
-   BUG_ON(!valid_dma_direction(dir));
-
-   page = virt_to_page(cpu_addr);
-   offset = (unsigned long)cpu_addr  ~PAGE_MASK;
-   addr = __dma_map_page(dev, page, offset, size, dir);
-   debug_dma_map_page(dev, page, offset, size, dir, addr, true);
-
-   return addr;
-}
-
-/**
- * dma_map_page - map a portion of a page for streaming DMA
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @page: page that buffer resides in
- * @offset: offset into page for start of buffer
- * @size: size of buffer to map
- * @dir: DMA transfer direction
- *
- * Ensure that any data held in the cache is appropriately discarded
- * or written back.
- *
- * The device owns this memory once this call has completed.  The CPU
- * can regain ownership by calling dma_unmap_page().
- */
-static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
-unsigned long offset, size_t size, enum dma_data_direction dir)
-{
-   dma_addr_t addr;
-
-   BUG_ON(!valid_dma_direction(dir));
-
-   addr = __dma_map_page(dev, page, offset, size, dir);
-   debug_dma_map_page(dev, page, offset, size, dir, addr, false);
-
-   return addr;
-}
-
-/**
- * dma_unmap_single - unmap a single buffer previously mapped
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @handle: DMA address of buffer
- * @size: size of buffer (same as passed to dma_map_single)
- * @dir: DMA transfer direction (same as passed to dma_map_single

RE: [PATCHv6 7/7] ARM: dma-mapping: add support for IOMMU mapper

2012-02-24 Thread Marek Szyprowski
Hello,

On Friday, February 24, 2012 1:50 PM Arnd Bergmann wrote:

 On Friday 24 February 2012, Marek Szyprowski wrote:
+static struct page **__iommu_alloc_buffer(struct device *dev, size_t
+size, gfp_t gfp) {
+ struct page **pages;
+ int count = size  PAGE_SHIFT;
+ int i=0;
+
+ pages = kzalloc(count * sizeof(struct page*), gfp);
+ if (!pages)
+ return NULL;
  
   kzalloc can fail for any size bigger than PAGE_SIZE, if the system memory 
   is
   fully fragmented.
   If there is a request for size bigger than 4MB, then the pages pointer 
   array won't
   Fit in one page and kzalloc may fail. we should use vzalloc()/vfree()
   when pages pointer array size needed is bigger than PAGE_SIZE.
 
  Right, thanks for spotting this. I will fix this in the next version.
 
 It's not clear though if that is the best solution. vzalloc comes at the
 price of using up space in the vmalloc area and as well as extra TLB entries,
 so we try to limit its use where possible. The other current code might fail
 in out of memory situations, but if a user wants to allocate a 4MB buffer
 (using up more than one physically contiguous page of pointers to pages), the
 following allocation of 1024 pages will likely fail as well, so we might
 just fail early.

I want to use some kind of chained arrays, each of at most of PAGE_SIZE. This 
code 
doesn't really need to keep these page pointers in contiguous virtual memory 
area, so
it will not be a problem here.

Best regards
-- 
Marek Szyprowski
Samsung Poland RD Center


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCHv7 4/9] ARM: dma-mapping: use asm-generic/dma-mapping-common.h

2012-02-29 Thread Marek Szyprowski
This patch modifies dma-mapping implementation on ARM architecture to
use common dma_map_ops structure and asm-generic/dma-mapping-common.h
helpers.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
Signed-off-by: Kyungmin Park kyungmin.p...@samsung.com
---
 arch/arm/Kconfig   |1 +
 arch/arm/include/asm/device.h  |1 +
 arch/arm/include/asm/dma-mapping.h |  196 +---
 arch/arm/mm/dma-mapping.c  |  148 ---
 4 files changed, 115 insertions(+), 231 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a48aecc..59102fb 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -4,6 +4,7 @@ config ARM
select HAVE_AOUT
select HAVE_DMA_API_DEBUG
select HAVE_IDE if PCI || ISA || PCMCIA
+   select HAVE_DMA_ATTRS
select HAVE_MEMBLOCK
select RTC_LIB
select SYS_SUPPORTS_APM_EMULATION
diff --git a/arch/arm/include/asm/device.h b/arch/arm/include/asm/device.h
index 7aa3680..6e2cb0e 100644
--- a/arch/arm/include/asm/device.h
+++ b/arch/arm/include/asm/device.h
@@ -7,6 +7,7 @@
 #define ASMARM_DEVICE_H
 
 struct dev_archdata {
+   struct dma_map_ops  *dma_ops;
 #ifdef CONFIG_DMABOUNCE
struct dmabounce_device_info *dmabounce;
 #endif
diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index ba422f2..6aea6ca 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -11,6 +11,27 @@
 #include asm/memory.h
 
 #define ARM_DMA_ERROR  ~0
+extern struct dma_map_ops arm_dma_ops;
+
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+   if (dev  dev-archdata.dma_ops)
+   return dev-archdata.dma_ops;
+   return arm_dma_ops;
+}
+
+static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
+{
+   BUG_ON(!dev);
+   dev-archdata.dma_ops = ops;
+}
+
+#include asm-generic/dma-mapping-common.h
+
+static inline int dma_set_mask(struct device *dev, u64 mask)
+{
+   return get_dma_ops(dev)-set_dma_mask(dev, mask);
+}
 
 #ifdef __arch_page_to_dma
 #error Please update to __arch_pfn_to_dma
@@ -119,7 +140,6 @@ static inline void __dma_page_dev_to_cpu(struct page *page, 
unsigned long off,
 
 extern int dma_supported(struct device *, u64);
 extern int dma_set_mask(struct device *, u64);
-
 /*
  * DMA errors are defined by all-bits-set in the DMA address.
  */
@@ -297,179 +317,17 @@ static inline void __dma_unmap_page(struct device *dev, 
dma_addr_t handle,
 }
 #endif /* CONFIG_DMABOUNCE */
 
-/**
- * dma_map_single - map a single buffer for streaming DMA
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @cpu_addr: CPU direct mapped address of buffer
- * @size: size of buffer to map
- * @dir: DMA transfer direction
- *
- * Ensure that any data held in the cache is appropriately discarded
- * or written back.
- *
- * The device owns this memory once this call has completed.  The CPU
- * can regain ownership by calling dma_unmap_single() or
- * dma_sync_single_for_cpu().
- */
-static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
-   size_t size, enum dma_data_direction dir)
-{
-   unsigned long offset;
-   struct page *page;
-   dma_addr_t addr;
-
-   BUG_ON(!virt_addr_valid(cpu_addr));
-   BUG_ON(!virt_addr_valid(cpu_addr + size - 1));
-   BUG_ON(!valid_dma_direction(dir));
-
-   page = virt_to_page(cpu_addr);
-   offset = (unsigned long)cpu_addr  ~PAGE_MASK;
-   addr = __dma_map_page(dev, page, offset, size, dir);
-   debug_dma_map_page(dev, page, offset, size, dir, addr, true);
-
-   return addr;
-}
-
-/**
- * dma_map_page - map a portion of a page for streaming DMA
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @page: page that buffer resides in
- * @offset: offset into page for start of buffer
- * @size: size of buffer to map
- * @dir: DMA transfer direction
- *
- * Ensure that any data held in the cache is appropriately discarded
- * or written back.
- *
- * The device owns this memory once this call has completed.  The CPU
- * can regain ownership by calling dma_unmap_page().
- */
-static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
-unsigned long offset, size_t size, enum dma_data_direction dir)
-{
-   dma_addr_t addr;
-
-   BUG_ON(!valid_dma_direction(dir));
-
-   addr = __dma_map_page(dev, page, offset, size, dir);
-   debug_dma_map_page(dev, page, offset, size, dir, addr, false);
-
-   return addr;
-}
-
-/**
- * dma_unmap_single - unmap a single buffer previously mapped
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @handle: DMA address of buffer
- * @size: size of buffer (same as passed to dma_map_single)
- * @dir: DMA transfer direction (same as passed to dma_map_single)
- *
- * Unmap a single

[PATCHv7 8/9] ARM: dma-mapping: use alloc, mmap, free from dma_ops

2012-02-29 Thread Marek Szyprowski
This patch converts dma_alloc/free/mmap_{coherent,writecombine}
functions to use generic alloc/free/mmap methods from dma_map_ops
structure. A new DMA_ATTR_WRITE_COMBINE DMA attribute have been
introduced to implement writecombine methods.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
Signed-off-by: Kyungmin Park kyungmin.p...@samsung.com
---
 arch/arm/common/dmabounce.c|3 +
 arch/arm/include/asm/dma-mapping.h |  107 ++--
 arch/arm/mm/dma-mapping.c  |   53 ++
 3 files changed, 98 insertions(+), 65 deletions(-)

diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 119f487..dbae5ad 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -449,6 +449,9 @@ static int dmabounce_set_mask(struct device *dev, u64 
dma_mask)
 }
 
 static struct dma_map_ops dmabounce_ops = {
+   .alloc  = arm_dma_alloc,
+   .free   = arm_dma_free,
+   .mmap   = arm_dma_mmap,
.map_page   = dmabounce_map_page,
.unmap_page = dmabounce_unmap_page,
.sync_single_for_cpu= dmabounce_sync_for_cpu,
diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index 266cba6..4342b75 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -5,6 +5,7 @@
 
 #include linux/mm_types.h
 #include linux/scatterlist.h
+#include linux/dma-attrs.h
 #include linux/dma-debug.h
 
 #include asm-generic/dma-coherent.h
@@ -110,68 +111,115 @@ static inline void dma_free_noncoherent(struct device 
*dev, size_t size,
 extern int dma_supported(struct device *dev, u64 mask);
 
 /**
- * dma_alloc_coherent - allocate consistent memory for DMA
+ * arm_dma_alloc - allocate consistent memory for DMA
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
  * @size: required memory size
  * @handle: bus-specific DMA address
+ * @attrs: optinal attributes that specific mapping properties
  *
- * Allocate some uncached, unbuffered memory for a device for
- * performing DMA.  This function allocates pages, and will
- * return the CPU-viewed address, and sets @handle to be the
- * device-viewed address.
+ * Allocate some memory for a device for performing DMA.  This function
+ * allocates pages, and will return the CPU-viewed address, and sets @handle
+ * to be the device-viewed address.
  */
-extern void *dma_alloc_coherent(struct device *, size_t, dma_addr_t *, gfp_t);
+extern void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
+  gfp_t gfp, struct dma_attrs *attrs);
+
+#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+  dma_addr_t *dma_handle, gfp_t flag,
+  struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+   void *cpu_addr;
+   BUG_ON(!ops);
+
+   cpu_addr = ops-alloc(dev, size, dma_handle, flag, attrs);
+   debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr);
+   return cpu_addr;
+}
 
 /**
- * dma_free_coherent - free memory allocated by dma_alloc_coherent
+ * arm_dma_free - free memory allocated by arm_dma_alloc
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
  * @size: size of memory originally requested in dma_alloc_coherent
  * @cpu_addr: CPU-view address returned from dma_alloc_coherent
  * @handle: device-view address returned from dma_alloc_coherent
+ * @attrs: optinal attributes that specific mapping properties
  *
  * Free (and unmap) a DMA buffer previously allocated by
- * dma_alloc_coherent().
+ * arm_dma_alloc().
  *
  * References to memory and mappings associated with cpu_addr/handle
  * during and after this call executing are illegal.
  */
-extern void dma_free_coherent(struct device *, size_t, void *, dma_addr_t);
+extern void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
+dma_addr_t handle, struct dma_attrs *attrs);
+
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+void *cpu_addr, dma_addr_t dma_handle,
+struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+   BUG_ON(!ops);
+
+   debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+   ops-free(dev, size, cpu_addr, dma_handle, attrs);
+}
 
 /**
- * dma_mmap_coherent - map a coherent DMA allocation into user space
+ * arm_dma_mmap - map a coherent DMA allocation into user space
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
  * @vma: vm_area_struct describing requested user mapping
  * @cpu_addr: kernel CPU-view address returned from

RE: [PATCH v9 0/2] iommu/exynos: Add IOMMU/System MMU driver for Samsung Exynos

2012-03-01 Thread Marek Szyprowski
Hi,

On Tuesday, February 28, 2012 7:37 AM KyongHo Cho wrote:

 Changes since v8:
 - exynos_iommu_map/unmap() just works for the page sizes
that System MMU supports. (Joerg's comment)
 - 1 platform device for 1 H/W though a multimedia accelerator
with several System MMUs attached.
This make controlling System MMU simpler.
 - Information between System MMU and the accelerators:
Shifted to accelerator's device structure from System MMU's

Could you tell which kernel tree did you use as a base for this patch? 

It doesn't apply onto any of the known kernel trees (I've tried v3.2, v3.3-rc5 
and
kgene/for-next). It looks that you have used some internal tree because cannot 
find arch/arm/mach-exynos/clock-exynos5.c or 
arch/arm/mach-exynos/clock-exynos4212.c
files in any of the public git repositories. 

Best regards
-- 
Marek Szyprowski
Samsung Poland RD Center



___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


RE: [PATCH v12 3/3] iommu/exynos: Add iommu driver for Exynos Platforms

2012-03-26 Thread Marek Szyprowski
-start);
 + ret = -ENOENT;
 + goto err_res;
 + }
 + }
 +
 + for (i = 0; i  data-nsfrs; i++) {
 + ret = platform_get_irq(pdev, i);
 + if (ret = 0) {
 + dev_dbg(dev, Unable to find IRQ resource\n);
 + goto err_irq;
 + }
 +
 + ret = request_irq(ret, exynos_sysmmu_irq, 0,
 + dev_name(dev), data);
 + if (ret) {
 + dev_dbg(dev, Unabled to register interrupt handler\n);
 + goto err_irq;
 + }
 + }

Please look at those loops and the interrupt function above. Those for-loops 
over 
all the resources looks really ugly and makes the driver less portable. The 
previous 
version (v8 afair) had much cleaned design.

It would be better not to squash multiple sysmmu controllers into a single 
instance
of the driver. Please keep the driver simple. Sysmmu driver's resource should 
consist
only of one io register area and one irq, nothing more. Such approach will 
remove 
the need for all that custom data in platform_data and it also make the future 
integration much easier for other non-samsung platforms (the sysmmu hardware is 
also
used by other hw vendors). Support for device tree is also easier to add if the 
device
driver is kept simple (supporting only one instance of the hardware block).

The only reason I can see, which might have suggested you to squash hardware 
sysmmu 
controllers into one single instance was to provide the same virtual io mappings
for all these sub-devices (it is mainly used by fims-isp complex block). 

This can be achieved in a much clearer design by using one, common iommu domain 
and attaching all these separate iommu controllers to it. Of course this will 
also
require having a separate platform devices for each sub-device, but sooner or 
later
you will need them anyway. The good example here is the MFC module, which 
already
have separate devices: mfc_l and mfc_r for each memory controller.

 + if (dev_get_platdata(dev)) {
 + char *deli, *beg;
 + struct sysmmu_platform_data *platdata = dev_get_platdata(dev);
 +
 + beg = platdata-clockname;
 +
 + for (deli = beg; (*deli != '\0')  (*deli != ','); deli++)
 + /* NOTHING */;
 +
 + if (*deli == '\0')
 + deli = NULL;
 + else
 + *deli = '\0';
 +
 + data-clk[0] = clk_get(dev, beg);
 + if (IS_ERR(data-clk[0])) {
 + data-clk[0] = NULL;
 + dev_dbg(dev, No clock descriptor registered\n);
 + }
 +
 + if (data-clk[0]  deli) {
 + *deli = ',';
 + data-clk[1] = clk_get(dev, deli + 1);
 + if (IS_ERR(data-clk[1]))
 + data-clk[1] = NULL;
 + }
 +
 + data-dbgname = platdata-dbgname;
 + }

Passing clocks via platform data is also considered as a bad idea, especially 
if 
you need to parse string to extract the clock names. It would be much cleaner to
have 2 (or more if required) variants of sysmmu driver, each one for a different
version of the sysmmu hardware (I noticed only that some of the sysmmu units 
require one clock, the other require 2 clocks).

 +
 + data-sysmmu = dev;
 + rwlock_init(data-lock);
 + INIT_LIST_HEAD(data-node);
 +
 + __set_fault_handler(data, default_fault_handler);
 +
 + if (dev-parent)
 + pm_runtime_enable(dev);
 +
 + dev_dbg(dev, (%s) Initialized\n, data-dbgname);
 + return 0;
 +err_irq:
 + while (i--  0) {
 + int irq;
 +
 + irq = platform_get_irq(pdev, i);
 + free_irq(irq, data);
 + }
 +err_res:
 + while (data-nsfrs--  0)
 + iounmap(data-sfrbases[data-nsfrs]);
 + kfree(data-sfrbases);
 +err_init:
 + kfree(data);
 +err_alloc:
 + dev_err(dev, Failed to initialize\n);
 + return ret;
 +}
 +
 +static struct platform_driver exynos_sysmmu_driver = {
 + .probe  = exynos_sysmmu_probe,
 + .driver = {
 + .owner  = THIS_MODULE,
 + .name   = exynos-sysmmu,
 + }
 +};
 +

(snipped)

Best regards
-- 
Marek Szyprowski
Samsung Poland RD Center



___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


RE: [PATCHv7 9/9] ARM: dma-mapping: add support for IOMMU mapper

2012-03-29 Thread Marek Szyprowski
Hello,

On Thursday, March 29, 2012 9:19 AM Hiroshi Doyu wrote:

 On Wed, 29 Feb 2012 16:04:22 +0100
 Marek Szyprowski m.szyprow...@samsung.com wrote:
 
  This patch add a complete implementation of DMA-mapping API for
  devices that have IOMMU support. All DMA-mapping calls are supported.
 
  This patch contains some of the code kindly provided by Krishna Reddy
  vdu...@nvidia.com and Andrzej Pietrasiewicz andrze...@samsung.com
 
  Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
  Signed-off-by: Kyungmin Park kyungmin.p...@samsung.com
  Reviewed-by: Konrad Rzeszutek Wilk konrad.w...@oracle.com
  ---
   arch/arm/Kconfig |8 +
   arch/arm/include/asm/device.h|3 +
   arch/arm/include/asm/dma-iommu.h |   34 ++
   arch/arm/mm/dma-mapping.c|  726 
  +-
   arch/arm/mm/vmregion.h   |2 +-
   5 files changed, 758 insertions(+), 15 deletions(-)
   create mode 100644 arch/arm/include/asm/dma-iommu.h
 
 
 snip
 
  +/*
  + * Map a part of the scatter-gather list into contiguous io address space
  + */
  +static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
  + size_t size, dma_addr_t *handle,
  + enum dma_data_direction dir)
  +{
  +   struct dma_iommu_mapping *mapping = dev-archdata.mapping;
  +   dma_addr_t iova, iova_base;
  +   int ret = 0;
  +   unsigned int count;
  +   struct scatterlist *s;
  +
  +   size = PAGE_ALIGN(size);
  +   *handle = ARM_DMA_ERROR;
  +
  +   iova_base = iova = __alloc_iova(mapping, size);
  +   if (iova == ARM_DMA_ERROR)
  +   return -ENOMEM;
  +
  +   for (count = 0, s = sg; count  (size  PAGE_SHIFT); s = 
  sg_next(s))
  +   {
  +   phys_addr_t phys = page_to_phys(sg_page(s));
  +   unsigned int len = PAGE_ALIGN(s-offset + s-length);
  +
  +   if (!arch_is_coherent())
  +   __dma_page_cpu_to_dev(sg_page(s), s-offset, 
  s-length, dir);
  +
  +   ret = iommu_map(mapping-domain, iova, phys, len, 0);
  +   if (ret  0)
  +   goto fail;
  +   count += len  PAGE_SHIFT;
  +   iova += len;
  +   }
  +   *handle = iova_base;
  +
  +   return 0;
  +fail:
  +   iommu_unmap(mapping-domain, iova_base, count * PAGE_SIZE);
  +   __free_iova(mapping, iova_base, size);
  +   return ret;
  +}
 
 Do we need to set dma_address as below?

Nope, this one is not correct. Please check the arm_iommu_map_sg() function. It 
calls 
__map_sg_chunk() and gives it dma-dma_address as one of the arguments, so the 
dma 
address is correctly stored in the scatter list. Please note that scatterlist 
is really
non-trivial structure and information about physical memory pages/chunks is 
disjoint 
from the information about dma address space chunks, although both are stored 
on the 
same list. In arm_iommu_map_sg() 's' pointer is used for physical memory chunks 
and 
'dma' pointer is used for dma address space chunks. 

The number of dma address space chunks (returned by arm_iommu_map_sq) can be 
lower 
than the number of physical memory chunks (given as nents argument).

In case of IOMMU you usually construct the scatter list in such a way, that you 
get
only one dma address chunk (so in fact you get a buffer mapped contiguously in 
virtual io address space).

 From e8bcc3cdac5375b5d7f5ac5b3f716a11c1008f38 Mon Sep 17 00:00:00 2001
 From: Hiroshi DOYU hd...@nvidia.com
 Date: Thu, 29 Mar 2012 09:59:04 +0300
 Subject: [PATCH 1/1] ARM: dma-mapping: Fix dma_address in sglist
 
 s-dma_address wasn't set at mapping.
 
 Signed-off-by: Hiroshi DOYU hd...@nvidia.com
 ---
  arch/arm/mm/dma-mapping.c |2 ++
  1 files changed, 2 insertions(+), 0 deletions(-)
 
 diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
 index 3347c37..11a9d65 100644
 --- a/arch/arm/mm/dma-mapping.c
 +++ b/arch/arm/mm/dma-mapping.c
 @@ -,6 +,8 @@ static int __map_sg_chunk(struct device *dev, struct 
 scatterlist *sg,
   ret = iommu_map(mapping-domain, iova, phys, len, 0);
   if (ret  0)
   goto fail;
 + s-dma_address = iova;
 +
   count += len  PAGE_SHIFT;
   iova += len;
   }

The above patch is not needed at all.

Best regards
-- 
Marek Szyprowski
Samsung Poland RD Center


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


RE: [PATCHv7 9/9] ARM: dma-mapping: add support for IOMMU mapper

2012-03-30 Thread Marek Szyprowski
Hello,

On Friday, March 30, 2012 4:24 AM Krishna Reddy wrote:

 Hi,
 I have found a bug in arm_iommu_map_sg().
 
  +int arm_iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents,
  +enum dma_data_direction dir, struct dma_attrs *attrs) {
  +   struct scatterlist *s = sg, *dma = sg, *start = sg;
  +   int i, count = 0;
  +   unsigned int offset = s-offset;
  +   unsigned int size = s-offset + s-length;
  +   unsigned int max = dma_get_max_seg_size(dev);
  +
  +   for (i = 1; i  nents; i++) {
  +   s-dma_address = ARM_DMA_ERROR;
  +   s-dma_length = 0;
  +
  +   s = sg_next(s);
 
 With above code, the last sg element's dma_length is not getting set to zero.
 This causing additional incorrect  unmapping during arm_iommu_unmap_sg call 
 and
 leading to random crashes.
 The order of above three lines should be as follows.
   s = sg_next(s);
 
   s-dma_address = ARM_DMA_ERROR;
   s-dma_length = 0;
 

You are right, the order of those lines must be reversed. In all my test codes 
the 
scatter list was initially cleared, so I missed this typical off-by-one error. 
Thanks for spotting it!

Best regards
-- 
Marek Szyprowski
Samsung Poland RD Center


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCHv8 08/10] ARM: dma-mapping: remove redundant code and cleanup

2012-04-10 Thread Marek Szyprowski
This patch just performs a global cleanup in DMA mapping implementation
for ARM architecture. Some of the tiny helper functions have been moved
to the caller code, some have been merged together.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
Acked-by: Kyungmin Park kyungmin.p...@samsung.com
---
 arch/arm/mm/dma-mapping.c |   88 
 1 files changed, 24 insertions(+), 64 deletions(-)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 695c219..485c693 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -40,64 +40,12 @@
  * the CPU does do speculative prefetches, which means we clean caches
  * before transfers and delay cache invalidation until transfer completion.
  *
- * Private support functions: these are not part of the API and are
- * liable to change.  Drivers must not use these.
  */
-static inline void __dma_single_cpu_to_dev(const void *kaddr, size_t size,
-   enum dma_data_direction dir)
-{
-   extern void ___dma_single_cpu_to_dev(const void *, size_t,
-   enum dma_data_direction);
-
-   if (!arch_is_coherent())
-   ___dma_single_cpu_to_dev(kaddr, size, dir);
-}
-
-static inline void __dma_single_dev_to_cpu(const void *kaddr, size_t size,
-   enum dma_data_direction dir)
-{
-   extern void ___dma_single_dev_to_cpu(const void *, size_t,
-   enum dma_data_direction);
-
-   if (!arch_is_coherent())
-   ___dma_single_dev_to_cpu(kaddr, size, dir);
-}
-
-static inline void __dma_page_cpu_to_dev(struct page *page, unsigned long off,
-   size_t size, enum dma_data_direction dir)
-{
-   extern void ___dma_page_cpu_to_dev(struct page *, unsigned long,
+static void __dma_page_cpu_to_dev(struct page *, unsigned long,
size_t, enum dma_data_direction);
-
-   if (!arch_is_coherent())
-   ___dma_page_cpu_to_dev(page, off, size, dir);
-}
-
-static inline void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
-   size_t size, enum dma_data_direction dir)
-{
-   extern void ___dma_page_dev_to_cpu(struct page *, unsigned long,
+static void __dma_page_dev_to_cpu(struct page *, unsigned long,
size_t, enum dma_data_direction);
 
-   if (!arch_is_coherent())
-   ___dma_page_dev_to_cpu(page, off, size, dir);
-}
-
-
-static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
-unsigned long offset, size_t size, enum dma_data_direction dir)
-{
-   __dma_page_cpu_to_dev(page, offset, size, dir);
-   return pfn_to_dma(dev, page_to_pfn(page)) + offset;
-}
-
-static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
-   size_t size, enum dma_data_direction dir)
-{
-   __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
-   handle  ~PAGE_MASK, size, dir);
-}
-
 /**
  * arm_dma_map_page - map a portion of a page for streaming DMA
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
@@ -112,11 +60,13 @@ static inline void __dma_unmap_page(struct device *dev, 
dma_addr_t handle,
  * The device owns this memory once this call has completed.  The CPU
  * can regain ownership by calling dma_unmap_page().
  */
-static inline dma_addr_t arm_dma_map_page(struct device *dev, struct page 
*page,
+static dma_addr_t arm_dma_map_page(struct device *dev, struct page *page,
 unsigned long offset, size_t size, enum dma_data_direction dir,
 struct dma_attrs *attrs)
 {
-   return __dma_map_page(dev, page, offset, size, dir);
+   if (!arch_is_coherent())
+   __dma_page_cpu_to_dev(page, offset, size, dir);
+   return pfn_to_dma(dev, page_to_pfn(page)) + offset;
 }
 
 /**
@@ -133,27 +83,31 @@ static inline dma_addr_t arm_dma_map_page(struct device 
*dev, struct page *page,
  * After this call, reads by the CPU to the buffer are guaranteed to see
  * whatever the device wrote there.
  */
-static inline void arm_dma_unmap_page(struct device *dev, dma_addr_t handle,
+static void arm_dma_unmap_page(struct device *dev, dma_addr_t handle,
size_t size, enum dma_data_direction dir,
struct dma_attrs *attrs)
 {
-   __dma_unmap_page(dev, handle, size, dir);
+   if (!arch_is_coherent())
+   __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
+ handle  ~PAGE_MASK, size, dir);
 }
 
-static inline void arm_dma_sync_single_for_cpu(struct device *dev,
+static void arm_dma_sync_single_for_cpu(struct device *dev,
dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
unsigned int offset = handle  (PAGE_SIZE - 1);
struct page *page = pfn_to_page(dma_to_pfn(dev, handle-offset));
-   __dma_page_dev_to_cpu(page, offset, size, dir);
+   if (!arch_is_coherent())
+   __dma_page_dev_to_cpu(page, offset

[PATCHv8 01/10] common: add dma_mmap_from_coherent() function

2012-04-10 Thread Marek Szyprowski
Add a common helper for dma-mapping core for mapping a coherent buffer
to userspace.

Reported-by: Subash Patel subas...@gmail.com
Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
Acked-by: Kyungmin Park kyungmin.p...@samsung.com
---
 drivers/base/dma-coherent.c|   42 
 include/asm-generic/dma-coherent.h |4 ++-
 2 files changed, 45 insertions(+), 1 deletions(-)

diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c
index bb0025c..1b85949 100644
--- a/drivers/base/dma-coherent.c
+++ b/drivers/base/dma-coherent.c
@@ -10,6 +10,7 @@
 struct dma_coherent_mem {
void*virt_base;
dma_addr_t  device_base;
+   phys_addr_t pfn_base;
int size;
int flags;
unsigned long   *bitmap;
@@ -44,6 +45,7 @@ int dma_declare_coherent_memory(struct device *dev, 
dma_addr_t bus_addr,
 
dev-dma_mem-virt_base = mem_base;
dev-dma_mem-device_base = device_addr;
+   dev-dma_mem-pfn_base = PFN_DOWN(bus_addr);
dev-dma_mem-size = pages;
dev-dma_mem-flags = flags;
 
@@ -176,3 +178,43 @@ int dma_release_from_coherent(struct device *dev, int 
order, void *vaddr)
return 0;
 }
 EXPORT_SYMBOL(dma_release_from_coherent);
+
+/**
+ * dma_mmap_from_coherent() - try to mmap the memory allocated from
+ * per-device coherent memory pool to userspace
+ * @dev:   device from which the memory was allocated
+ * @vma:   vm_area for the userspace memory
+ * @vaddr: cpu address returned by dma_alloc_from_coherent
+ * @size:  size of the memory buffer allocated by dma_alloc_from_coherent
+ *
+ * This checks whether the memory was allocated from the per-device
+ * coherent memory pool and if so, maps that memory to the provided vma.
+ *
+ * Returns 1 if we correctly mapped the memory, or 0 if
+ * dma_release_coherent() should proceed with mapping memory from
+ * generic pools.
+ */
+int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
+  void *vaddr, size_t size, int *ret)
+{
+   struct dma_coherent_mem *mem = dev ? dev-dma_mem : NULL;
+
+   if (mem  vaddr = mem-virt_base  vaddr + size =
+  (mem-virt_base + (mem-size  PAGE_SHIFT))) {
+   unsigned long off = vma-vm_pgoff;
+   int start = (vaddr - mem-virt_base)  PAGE_SHIFT;
+   int user_count = (vma-vm_end - vma-vm_start)  PAGE_SHIFT;
+   int count = size  PAGE_SHIFT;
+
+   *ret = -ENXIO;
+   if (off  count  user_count = count - off) {
+   unsigned pfn = mem-pfn_base + start + off;
+   *ret = remap_pfn_range(vma, vma-vm_start, pfn,
+  user_count  PAGE_SHIFT,
+  vma-vm_page_prot);
+   }
+   return 1;
+   }
+   return 0;
+}
+EXPORT_SYMBOL(dma_mmap_from_coherent);
diff --git a/include/asm-generic/dma-coherent.h 
b/include/asm-generic/dma-coherent.h
index 85a3ffa..abfb268 100644
--- a/include/asm-generic/dma-coherent.h
+++ b/include/asm-generic/dma-coherent.h
@@ -3,13 +3,15 @@
 
 #ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT
 /*
- * These two functions are only for dma allocator.
+ * These three functions are only for dma allocator.
  * Don't use them in device drivers.
  */
 int dma_alloc_from_coherent(struct device *dev, ssize_t size,
   dma_addr_t *dma_handle, void **ret);
 int dma_release_from_coherent(struct device *dev, int order, void *vaddr);
 
+int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
+   void *cpu_addr, size_t size, int *ret);
 /*
  * Standard interface
  */
-- 
1.7.1.569.g6f426

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCHv8 05/10] ARM: dma-mapping: use asm-generic/dma-mapping-common.h

2012-04-10 Thread Marek Szyprowski
This patch modifies dma-mapping implementation on ARM architecture to
use common dma_map_ops structure and asm-generic/dma-mapping-common.h
helpers.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
Acked-by: Kyungmin Park kyungmin.p...@samsung.com
---
 arch/arm/Kconfig   |1 +
 arch/arm/include/asm/device.h  |1 +
 arch/arm/include/asm/dma-mapping.h |  196 +---
 arch/arm/mm/dma-mapping.c  |  148 ---
 4 files changed, 115 insertions(+), 231 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index cf006d4..0fd27d4 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -4,6 +4,7 @@ config ARM
select HAVE_AOUT
select HAVE_DMA_API_DEBUG
select HAVE_IDE if PCI || ISA || PCMCIA
+   select HAVE_DMA_ATTRS
select HAVE_MEMBLOCK
select RTC_LIB
select SYS_SUPPORTS_APM_EMULATION
diff --git a/arch/arm/include/asm/device.h b/arch/arm/include/asm/device.h
index 7aa3680..6e2cb0e 100644
--- a/arch/arm/include/asm/device.h
+++ b/arch/arm/include/asm/device.h
@@ -7,6 +7,7 @@
 #define ASMARM_DEVICE_H
 
 struct dev_archdata {
+   struct dma_map_ops  *dma_ops;
 #ifdef CONFIG_DMABOUNCE
struct dmabounce_device_info *dmabounce;
 #endif
diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index 02d651f..424b67a 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -11,6 +11,27 @@
 #include asm/memory.h
 
 #define ARM_DMA_ERROR  (~0)
+extern struct dma_map_ops arm_dma_ops;
+
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+   if (dev  dev-archdata.dma_ops)
+   return dev-archdata.dma_ops;
+   return arm_dma_ops;
+}
+
+static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
+{
+   BUG_ON(!dev);
+   dev-archdata.dma_ops = ops;
+}
+
+#include asm-generic/dma-mapping-common.h
+
+static inline int dma_set_mask(struct device *dev, u64 mask)
+{
+   return get_dma_ops(dev)-set_dma_mask(dev, mask);
+}
 
 #ifdef __arch_page_to_dma
 #error Please update to __arch_pfn_to_dma
@@ -119,7 +140,6 @@ static inline void __dma_page_dev_to_cpu(struct page *page, 
unsigned long off,
 
 extern int dma_supported(struct device *, u64);
 extern int dma_set_mask(struct device *, u64);
-
 /*
  * DMA errors are defined by all-bits-set in the DMA address.
  */
@@ -297,179 +317,17 @@ static inline void __dma_unmap_page(struct device *dev, 
dma_addr_t handle,
 }
 #endif /* CONFIG_DMABOUNCE */
 
-/**
- * dma_map_single - map a single buffer for streaming DMA
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @cpu_addr: CPU direct mapped address of buffer
- * @size: size of buffer to map
- * @dir: DMA transfer direction
- *
- * Ensure that any data held in the cache is appropriately discarded
- * or written back.
- *
- * The device owns this memory once this call has completed.  The CPU
- * can regain ownership by calling dma_unmap_single() or
- * dma_sync_single_for_cpu().
- */
-static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
-   size_t size, enum dma_data_direction dir)
-{
-   unsigned long offset;
-   struct page *page;
-   dma_addr_t addr;
-
-   BUG_ON(!virt_addr_valid(cpu_addr));
-   BUG_ON(!virt_addr_valid(cpu_addr + size - 1));
-   BUG_ON(!valid_dma_direction(dir));
-
-   page = virt_to_page(cpu_addr);
-   offset = (unsigned long)cpu_addr  ~PAGE_MASK;
-   addr = __dma_map_page(dev, page, offset, size, dir);
-   debug_dma_map_page(dev, page, offset, size, dir, addr, true);
-
-   return addr;
-}
-
-/**
- * dma_map_page - map a portion of a page for streaming DMA
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @page: page that buffer resides in
- * @offset: offset into page for start of buffer
- * @size: size of buffer to map
- * @dir: DMA transfer direction
- *
- * Ensure that any data held in the cache is appropriately discarded
- * or written back.
- *
- * The device owns this memory once this call has completed.  The CPU
- * can regain ownership by calling dma_unmap_page().
- */
-static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
-unsigned long offset, size_t size, enum dma_data_direction dir)
-{
-   dma_addr_t addr;
-
-   BUG_ON(!valid_dma_direction(dir));
-
-   addr = __dma_map_page(dev, page, offset, size, dir);
-   debug_dma_map_page(dev, page, offset, size, dir, addr, false);
-
-   return addr;
-}
-
-/**
- * dma_unmap_single - unmap a single buffer previously mapped
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @handle: DMA address of buffer
- * @size: size of buffer (same as passed to dma_map_single)
- * @dir: DMA transfer direction (same as passed to dma_map_single)
- *
- * Unmap a single streaming

[PATCHv8 04/10] ARM: dma-mapping: remove offset parameter to prepare for generic dma_ops

2012-04-10 Thread Marek Szyprowski
This patch removes the need for offset parameter in dma bounce
functions. This is required to let dma-mapping framework on ARM
architecture use common, generic dma-mapping helpers.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
Acked-by: Kyungmin Park kyungmin.p...@samsung.com
---
 arch/arm/common/dmabounce.c|   13 +--
 arch/arm/include/asm/dma-mapping.h |   67 +--
 arch/arm/mm/dma-mapping.c  |4 +-
 3 files changed, 45 insertions(+), 39 deletions(-)

diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index a1abdc9..c9f54b6 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -173,7 +173,8 @@ find_safe_buffer(struct dmabounce_device_info *device_info, 
dma_addr_t safe_dma_
read_lock_irqsave(device_info-lock, flags);
 
list_for_each_entry(b, device_info-safe_buffers, node)
-   if (b-safe_dma_addr == safe_dma_addr) {
+   if (b-safe_dma_addr = safe_dma_addr 
+   b-safe_dma_addr + b-size  safe_dma_addr) {
rb = b;
break;
}
@@ -362,9 +363,10 @@ void __dma_unmap_page(struct device *dev, dma_addr_t 
dma_addr, size_t size,
 EXPORT_SYMBOL(__dma_unmap_page);
 
 int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr,
-   unsigned long off, size_t sz, enum dma_data_direction dir)
+   size_t sz, enum dma_data_direction dir)
 {
struct safe_buffer *buf;
+   unsigned long off;
 
dev_dbg(dev, %s(dma=%#x,off=%#lx,sz=%zx,dir=%x)\n,
__func__, addr, off, sz, dir);
@@ -373,6 +375,8 @@ int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t 
addr,
if (!buf)
return 1;
 
+   off = addr - buf-safe_dma_addr;
+
BUG_ON(buf-direction != dir);
 
dev_dbg(dev, %s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n,
@@ -391,9 +395,10 @@ int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t 
addr,
 EXPORT_SYMBOL(dmabounce_sync_for_cpu);
 
 int dmabounce_sync_for_device(struct device *dev, dma_addr_t addr,
-   unsigned long off, size_t sz, enum dma_data_direction dir)
+   size_t sz, enum dma_data_direction dir)
 {
struct safe_buffer *buf;
+   unsigned long off;
 
dev_dbg(dev, %s(dma=%#x,off=%#lx,sz=%zx,dir=%x)\n,
__func__, addr, off, sz, dir);
@@ -402,6 +407,8 @@ int dmabounce_sync_for_device(struct device *dev, 
dma_addr_t addr,
if (!buf)
return 1;
 
+   off = addr - buf-safe_dma_addr;
+
BUG_ON(buf-direction != dir);
 
dev_dbg(dev, %s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n,
diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index 3dbec1d..02d651f 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -266,19 +266,17 @@ extern void __dma_unmap_page(struct device *, dma_addr_t, 
size_t,
 /*
  * Private functions
  */
-int dmabounce_sync_for_cpu(struct device *, dma_addr_t, unsigned long,
-   size_t, enum dma_data_direction);
-int dmabounce_sync_for_device(struct device *, dma_addr_t, unsigned long,
-   size_t, enum dma_data_direction);
+int dmabounce_sync_for_cpu(struct device *, dma_addr_t, size_t, enum 
dma_data_direction);
+int dmabounce_sync_for_device(struct device *, dma_addr_t, size_t, enum 
dma_data_direction);
 #else
 static inline int dmabounce_sync_for_cpu(struct device *d, dma_addr_t addr,
-   unsigned long offset, size_t size, enum dma_data_direction dir)
+   size_t size, enum dma_data_direction dir)
 {
return 1;
 }
 
 static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr,
-   unsigned long offset, size_t size, enum dma_data_direction dir)
+   size_t size, enum dma_data_direction dir)
 {
return 1;
 }
@@ -401,6 +399,33 @@ static inline void dma_unmap_page(struct device *dev, 
dma_addr_t handle,
__dma_unmap_page(dev, handle, size, dir);
 }
 
+
+static inline void dma_sync_single_for_cpu(struct device *dev,
+   dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+   BUG_ON(!valid_dma_direction(dir));
+
+   debug_dma_sync_single_for_cpu(dev, handle, size, dir);
+
+   if (!dmabounce_sync_for_cpu(dev, handle, size, dir))
+   return;
+
+   __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
+}
+
+static inline void dma_sync_single_for_device(struct device *dev,
+   dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+   BUG_ON(!valid_dma_direction(dir));
+
+   debug_dma_sync_single_for_device(dev, handle, size, dir);
+
+   if (!dmabounce_sync_for_device(dev, handle, size, dir))
+   return;
+
+   __dma_single_cpu_to_dev(dma_to_virt(dev, handle), size, dir);
+}
+
 /**
  * dma_sync_single_range_for_cpu
  * @dev

[PATCHv8 09/10] ARM: dma-mapping: use alloc, mmap, free from dma_ops

2012-04-10 Thread Marek Szyprowski
This patch converts dma_alloc/free/mmap_{coherent,writecombine}
functions to use generic alloc/free/mmap methods from dma_map_ops
structure. A new DMA_ATTR_WRITE_COMBINE DMA attribute have been
introduced to implement writecombine methods.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
Acked-by: Kyungmin Park kyungmin.p...@samsung.com
---
 arch/arm/common/dmabounce.c|3 +
 arch/arm/include/asm/dma-mapping.h |  107 ++--
 arch/arm/mm/dma-mapping.c  |   54 ++
 3 files changed, 98 insertions(+), 66 deletions(-)

diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 119f487..dbae5ad 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -449,6 +449,9 @@ static int dmabounce_set_mask(struct device *dev, u64 
dma_mask)
 }
 
 static struct dma_map_ops dmabounce_ops = {
+   .alloc  = arm_dma_alloc,
+   .free   = arm_dma_free,
+   .mmap   = arm_dma_mmap,
.map_page   = dmabounce_map_page,
.unmap_page = dmabounce_unmap_page,
.sync_single_for_cpu= dmabounce_sync_for_cpu,
diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index 5f35f22..d56d6d2 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -5,6 +5,7 @@
 
 #include linux/mm_types.h
 #include linux/scatterlist.h
+#include linux/dma-attrs.h
 #include linux/dma-debug.h
 
 #include asm-generic/dma-coherent.h
@@ -110,68 +111,115 @@ static inline void dma_free_noncoherent(struct device 
*dev, size_t size,
 extern int dma_supported(struct device *dev, u64 mask);
 
 /**
- * dma_alloc_coherent - allocate consistent memory for DMA
+ * arm_dma_alloc - allocate consistent memory for DMA
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
  * @size: required memory size
  * @handle: bus-specific DMA address
+ * @attrs: optinal attributes that specific mapping properties
  *
- * Allocate some uncached, unbuffered memory for a device for
- * performing DMA.  This function allocates pages, and will
- * return the CPU-viewed address, and sets @handle to be the
- * device-viewed address.
+ * Allocate some memory for a device for performing DMA.  This function
+ * allocates pages, and will return the CPU-viewed address, and sets @handle
+ * to be the device-viewed address.
  */
-extern void *dma_alloc_coherent(struct device *, size_t, dma_addr_t *, gfp_t);
+extern void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
+  gfp_t gfp, struct dma_attrs *attrs);
+
+#define dma_alloc_coherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+  dma_addr_t *dma_handle, gfp_t flag,
+  struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+   void *cpu_addr;
+   BUG_ON(!ops);
+
+   cpu_addr = ops-alloc(dev, size, dma_handle, flag, attrs);
+   debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr);
+   return cpu_addr;
+}
 
 /**
- * dma_free_coherent - free memory allocated by dma_alloc_coherent
+ * arm_dma_free - free memory allocated by arm_dma_alloc
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
  * @size: size of memory originally requested in dma_alloc_coherent
  * @cpu_addr: CPU-view address returned from dma_alloc_coherent
  * @handle: device-view address returned from dma_alloc_coherent
+ * @attrs: optinal attributes that specific mapping properties
  *
  * Free (and unmap) a DMA buffer previously allocated by
- * dma_alloc_coherent().
+ * arm_dma_alloc().
  *
  * References to memory and mappings associated with cpu_addr/handle
  * during and after this call executing are illegal.
  */
-extern void dma_free_coherent(struct device *, size_t, void *, dma_addr_t);
+extern void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
+dma_addr_t handle, struct dma_attrs *attrs);
+
+#define dma_free_coherent(d, s, c, h) dma_free_attrs(d, s, c, h, NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+void *cpu_addr, dma_addr_t dma_handle,
+struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+   BUG_ON(!ops);
+
+   debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+   ops-free(dev, size, cpu_addr, dma_handle, attrs);
+}
 
 /**
- * dma_mmap_coherent - map a coherent DMA allocation into user space
+ * arm_dma_mmap - map a coherent DMA allocation into user space
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
  * @vma: vm_area_struct describing requested user mapping
  * @cpu_addr: kernel CPU-view address

[PATCHv8 06/10] ARM: dma-mapping: implement dma sg methods on top of any generic dma ops

2012-04-10 Thread Marek Szyprowski
This patch converts all dma_sg methods to be generic (independent of the
current DMA mapping implementation for ARM architecture). All dma sg
operations are now implemented on top of respective
dma_map_page/dma_sync_single_for* operations from dma_map_ops structure.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
Acked-by: Kyungmin Park kyungmin.p...@samsung.com
---
 arch/arm/mm/dma-mapping.c |   43 +++
 1 files changed, 19 insertions(+), 24 deletions(-)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 4841fec..d7137bd 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -619,7 +619,7 @@ void ___dma_page_dev_to_cpu(struct page *page, unsigned 
long off,
 EXPORT_SYMBOL(___dma_page_dev_to_cpu);
 
 /**
- * dma_map_sg - map a set of SG buffers for streaming mode DMA
+ * arm_dma_map_sg - map a set of SG buffers for streaming mode DMA
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
  * @sg: list of buffers
  * @nents: number of buffers to map
@@ -637,12 +637,13 @@ EXPORT_SYMBOL(___dma_page_dev_to_cpu);
 int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction dir, struct dma_attrs *attrs)
 {
+   struct dma_map_ops *ops = get_dma_ops(dev);
struct scatterlist *s;
int i, j;
 
for_each_sg(sg, s, nents, i) {
-   s-dma_address = __dma_map_page(dev, sg_page(s), s-offset,
-   s-length, dir);
+   s-dma_address = ops-map_page(dev, sg_page(s), s-offset,
+   s-length, dir, attrs);
if (dma_mapping_error(dev, s-dma_address))
goto bad_mapping;
}
@@ -650,12 +651,12 @@ int arm_dma_map_sg(struct device *dev, struct scatterlist 
*sg, int nents,
 
  bad_mapping:
for_each_sg(sg, s, i, j)
-   __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
+   ops-unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir, 
attrs);
return 0;
 }
 
 /**
- * dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg
+ * arm_dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
  * @sg: list of buffers
  * @nents: number of buffers to unmap (same as was passed to dma_map_sg)
@@ -667,15 +668,17 @@ int arm_dma_map_sg(struct device *dev, struct scatterlist 
*sg, int nents,
 void arm_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction dir, struct dma_attrs *attrs)
 {
+   struct dma_map_ops *ops = get_dma_ops(dev);
struct scatterlist *s;
+
int i;
 
for_each_sg(sg, s, nents, i)
-   __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
+   ops-unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir, 
attrs);
 }
 
 /**
- * dma_sync_sg_for_cpu
+ * arm_dma_sync_sg_for_cpu
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
  * @sg: list of buffers
  * @nents: number of buffers to map (returned from dma_map_sg)
@@ -684,21 +687,17 @@ void arm_dma_unmap_sg(struct device *dev, struct 
scatterlist *sg, int nents,
 void arm_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir)
 {
+   struct dma_map_ops *ops = get_dma_ops(dev);
struct scatterlist *s;
int i;
 
-   for_each_sg(sg, s, nents, i) {
-   if (!dmabounce_sync_for_cpu(dev, sg_dma_address(s),
-   sg_dma_len(s), dir))
-   continue;
-
-   __dma_page_dev_to_cpu(sg_page(s), s-offset,
- s-length, dir);
-   }
+   for_each_sg(sg, s, nents, i)
+   ops-sync_single_for_cpu(dev, sg_dma_address(s), s-length,
+dir);
 }
 
 /**
- * dma_sync_sg_for_device
+ * arm_dma_sync_sg_for_device
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
  * @sg: list of buffers
  * @nents: number of buffers to map (returned from dma_map_sg)
@@ -707,17 +706,13 @@ void arm_dma_sync_sg_for_cpu(struct device *dev, struct 
scatterlist *sg,
 void arm_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir)
 {
+   struct dma_map_ops *ops = get_dma_ops(dev);
struct scatterlist *s;
int i;
 
-   for_each_sg(sg, s, nents, i) {
-   if (!dmabounce_sync_for_device(dev, sg_dma_address(s),
-   sg_dma_len(s), dir))
-   continue;
-
-   __dma_page_cpu_to_dev(sg_page(s), s-offset,
- s-length, dir

RE: [PATCHv8 07/10] ARM: dma-mapping: move all dma bounce code to separate dma ops structure

2012-04-10 Thread Marek Szyprowski
Hi Arnd,

On Tuesday, April 10, 2012 2:24 PM Arnd Bergmann wrote:

 On Tuesday 10 April 2012, Marek Szyprowski wrote:
  This patch removes dma bounce hooks from the common dma mapping
  implementation on ARM architecture and creates a separate set of
  dma_map_ops for dma bounce devices.
 
  Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
  Acked-by: Kyungmin Park kyungmin.p...@samsung.com
 
 I could be misunderstanding something, but it looks like this
 one should come before patch 6, where you remove
 some of the dmabounce functions. Can you clarify?

Before patch no 6, there were custom methods for all scatter/gather
related operations. They iterated over the whole scatter list and called
cache related operations directly (which in turn checked if we use dma
bounce code or not and called respective version). Patch no 6 changed
them not to use such shortcut for direct calling cache related operations.

Instead it provides similar loop over scatter list and calls methods
from the current device's dma_map_ops structure. This way, after patch no 
7 these functions call simple dma_map_page() method for all standard 
devices and dma bounce aware version for devices registered for dma 
bouncing (with use different dma_map_ops).

I can provide a separate set of scatter/gather list related functions for
the linear dma mapping implementation and dma bouncing implementation 
if you think that the current approach is too complicated or 
over-engineered.

Best regards
-- 
Marek Szyprowski
Samsung Poland RD Center


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


RE: [PATCHv8 10/10] ARM: dma-mapping: add support for IOMMU mapper

2012-04-10 Thread Marek Szyprowski
Hi Arnd,

On Tuesday, April 10, 2012 1:58 PM Arnd Bergmann wrote:

 On Tuesday 10 April 2012, Marek Szyprowski wrote:
  +/**
  + * arm_iommu_create_mapping
  + * @bus: pointer to the bus holding the client device (for IOMMU calls)
  + * @base: start address of the valid IO address space
  + * @size: size of the valid IO address space
  + * @order: accuracy of the IO addresses allocations
  + *
  + * Creates a mapping structure which holds information about used/unused
  + * IO address ranges, which is required to perform memory allocation and
  + * mapping with IOMMU aware functions.
  + *
  + * The client device need to be attached to the mapping with
  + * arm_iommu_attach_device function.
  + */
  +struct dma_iommu_mapping *
  +arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t 
  size,
  +int order)
  +{
  +   unsigned int count = size  (PAGE_SHIFT + order);
  +   unsigned int bitmap_size = BITS_TO_LONGS(count) * sizeof(long);
  +   struct dma_iommu_mapping *mapping;
  +   int err = -ENOMEM;
  +
  +   if (!count)
  +   return ERR_PTR(-EINVAL);
  +
  +   mapping = kzalloc(sizeof(struct dma_iommu_mapping), GFP_KERNEL);
  +   if (!mapping)
  +   goto err;
  +
  +   mapping-bitmap = kzalloc(bitmap_size, GFP_KERNEL);
  +   if (!mapping-bitmap)
  +   goto err2;
  +
  +   mapping-base = base;
  +   mapping-bits = BITS_PER_BYTE * bitmap_size;
  +   mapping-order = order;
  +   spin_lock_init(mapping-lock);
  +
  +   mapping-domain = iommu_domain_alloc(bus);
  +   if (!mapping-domain)
  +   goto err3;
  +
  +   kref_init(mapping-kref);
  +   return mapping;
  +err3:
  +   kfree(mapping-bitmap);
  +err2:
  +   kfree(mapping);
  +err:
  +   return ERR_PTR(err);
  +}
  +EXPORT_SYMBOL(arm_iommu_create_mapping);
 
 I don't understand this function, mostly I guess because you have not
 provided any users. A few questions here:
 
 * What is ARM specific about it that it is named arm_iommu_create_mapping?
   Isn't this completely generic, at least on the interface side?
 
 * Why is this exported to modules? Which device drivers do you expect
   to call it?
 
 * Why do you pass the bus_type in here? That seems like the completely
   wrong thing to do when all devices are on the same bus type (e.g.
   amba or platform) but are connected to different instances that each
   have their own iommu. I guess this is a question for Jörg, because the
   base iommu interface provides iommu_domain_alloc().

I will soon post a patch which shows how my IOMMU aware dma-mapping 
integrates with Samsung Exynos4 SYSMMU driver, so I will be able to answer
all your questions by pointing to the respective lines in either IOMMU
framework or my integration code.

Best regards
-- 
Marek Szyprowski
Samsung Poland RD Center


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


RE: [PATCHv8 04/10] ARM: dma-mapping: remove offset parameter to prepare for generic dma_ops

2012-04-11 Thread Marek Szyprowski
Hi Arnd,

On Tuesday, April 10, 2012 1:43 PM Arnd Bergmann wrote:

 On Tuesday 10 April 2012, Marek Szyprowski wrote:
  This patch removes the need for offset parameter in dma bounce
  functions. This is required to let dma-mapping framework on ARM
  architecture use common, generic dma-mapping helpers.
 
  Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
  Acked-by: Kyungmin Park kyungmin.p...@samsung.com
 
 This one worries me a little. I always thought that the range sync
 functions were specifically needed for the dmabounce code. At the
 very least, I would expect the changeset comment to have an explanation
 of why this was initially done this way and why it's now safe to do
 do it otherwise.

Well, range sync functions are available from the early days of the dma 
mapping api (at least that's what I've found reading the change log and
old patches). They are the correct way of doing a partial syncs on the 
buffer (usually used by the network device drivers). This patch changes
only the internal implementation of the dma bounce functions to let 
them tunnel through dma_map_ops structure. The driver api stays
unchanged, so driver are obliged to call dma_*_range_* functions to
keep code clean and easy to understand. 

The only drawback I can see from this patch is reduced detection of
the dma api abuse. Let us consider the following code:

dma_addr = dma_map_single(dev, ptr, 64, DMA_TO_DEVICE);
dma_sync_single_range_for_cpu(dev, dma_addr+16, 0, 32, DMA_TO_DEVICE);

Without the patch such code fails, because dma bounce code is unable
to find the bounce buffer for the given dma_address. After the patch
the sync call will be equivalent to: 

dma_sync_single_range_for_cpu(dev, dma_addr, 16, 32, DMA_TO_DEVICE);

which succeeds.

I don't consider this as a real problem. DMA API abuse should be caught
by debug_dma_* function family, so we can simplify the internal low-level
implementation without losing anything.

Best regards
-- 
Marek Szyprowski
Samsung Poland RD Center


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


RE: [PATCHv8 05/10] ARM: dma-mapping: use asm-generic/dma-mapping-common.h

2012-04-11 Thread Marek Szyprowski
Hi Arnd,

On Tuesday, April 10, 2012 1:47 PM Arnd Bergmann wrote:

 On Tuesday 10 April 2012, Marek Szyprowski wrote:
  This patch modifies dma-mapping implementation on ARM architecture to
  use common dma_map_ops structure and asm-generic/dma-mapping-common.h
  helpers.
 
  Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
  Acked-by: Kyungmin Park kyungmin.p...@samsung.com
  ---
   arch/arm/Kconfig   |1 +
   arch/arm/include/asm/device.h  |1 +
   arch/arm/include/asm/dma-mapping.h |  196 
  +---
   arch/arm/mm/dma-mapping.c  |  148 ---
   4 files changed, 115 insertions(+), 231 deletions(-)
 
 Looks good in principle. One question: Now that many of the functions are only
 used in the dma_map_ops, can you make them 'static' instead?

Some of these non static functions (mainly arm_dma_*_sg_* family) are also used 
by dma bounce
code introduced in the next patch, that's why I left them without static 
attribute.

Best regards
-- 
Marek Szyprowski
Samsung Poland RD Center


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


RE: [PATCHv8 04/10] ARM: dma-mapping: remove offset parameter to prepare for generic dma_ops

2012-04-11 Thread Marek Szyprowski
Hi Arnd,

On Wednesday, April 11, 2012 2:19 PM Arnd Bergmann wrote:

 On Wednesday 11 April 2012, Marek Szyprowski wrote:
  Well, range sync functions are available from the early days of the dma
  mapping api (at least that's what I've found reading the change log and
  old patches). They are the correct way of doing a partial syncs on the
  buffer (usually used by the network device drivers). This patch changes
  only the internal implementation of the dma bounce functions to let
  them tunnel through dma_map_ops structure. The driver api stays
  unchanged, so driver are obliged to call dma_*_range_* functions to
  keep code clean and easy to understand.
 
  The only drawback I can see from this patch is reduced detection of
  the dma api abuse. Let us consider the following code:
 
  dma_addr = dma_map_single(dev, ptr, 64, DMA_TO_DEVICE);
  dma_sync_single_range_for_cpu(dev, dma_addr+16, 0, 32, DMA_TO_DEVICE);
 
  Without the patch such code fails, because dma bounce code is unable
  to find the bounce buffer for the given dma_address. After the patch
  the sync call will be equivalent to:
 
  dma_sync_single_range_for_cpu(dev, dma_addr, 16, 32, DMA_TO_DEVICE);
 
  which succeeds.
 
  I don't consider this as a real problem. DMA API abuse should be caught
  by debug_dma_* function family, so we can simplify the internal low-level
  implementation without losing anything.
 
 
 Ok, fair enough. Can you put the above text into the changelog?

Yes, I will update it in the next release.

Best regards
-- 
Marek Szyprowski
Samsung Poland RD Center


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 0/2] Exynos: fix SYSMMU driver to work with power domains

2012-04-11 Thread Marek Szyprowski
Hi!

These two patches fixes operation of the SYSMMU driver (v12 version [1])
with the new power domain driver based on generic power domains and
runtime pw, which has been merged to Linux kernel v3.4-rc1.

[1] https://lkml.org/lkml/2012/3/15/51

Best regards
Marek Szyprowski
Samsung Poland RD Center


Patch summary:

Marek Szyprowski (2):
  iommu/exynos: fix runtime pm support
  ARM: Exynos4: update SYSMMU setup code for gen_pd power domain driver

 arch/arm/mach-exynos/dev-sysmmu.c |6 +-
 arch/arm/mach-exynos/pm_domains.c |   13 +
 drivers/iommu/exynos-iommu.c  |   20 ++--
 3 files changed, 36 insertions(+), 3 deletions(-)

-- 
1.7.1.569.g6f426
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 1/2] iommu/exynos: fix runtime pm support

2012-04-11 Thread Marek Szyprowski
Fix registration to runtime pw and add missing resume callback.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
Acked-by: Kyungmin Park kyungmin.p...@samsung.com
---
 drivers/iommu/exynos-iommu.c |   20 ++--
 1 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index b8daf7c..eef924d 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -651,8 +651,7 @@ static int exynos_sysmmu_probe(struct platform_device *pdev)
 
__set_fault_handler(data, default_fault_handler);
 
-   if (dev-parent)
-   pm_runtime_enable(dev);
+   pm_runtime_enable(dev);
 
dev_dbg(dev, (%s) Initialized\n, data-dbgname);
return 0;
@@ -674,11 +673,28 @@ err_alloc:
return ret;
 }
 
+static int exynos_pm_resume(struct device *dev)
+{
+   struct sysmmu_drvdata *data;
+
+   data = dev_get_drvdata(dev);
+
+   if (is_sysmmu_active(data))
+   __exynos_sysmmu_enable(data, data-pgtable, NULL);
+
+   return 0;
+}
+
+const struct dev_pm_ops exynos_pm_ops = {
+   .resume = exynos_pm_resume,
+};
+
 static struct platform_driver exynos_sysmmu_driver = {
.probe  = exynos_sysmmu_probe,
.driver = {
.owner  = THIS_MODULE,
.name   = exynos-sysmmu,
+   .pm = exynos_pm_ops,
}
 };
 
-- 
1.7.1.569.g6f426

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 2/2] ARM: Exynos4: update SYSMMU setup code for gen_pd power domain driver

2012-04-11 Thread Marek Szyprowski
SYSMMU platform devices must be registered before setting up power
domains to let power domain driver to correctly register also SYSMMU
controller devices. This patch also registers SYSMMU controller devices
to respective power domains.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
Acked-by: Kyungmin Park kyungmin.p...@samsung.com
---
 arch/arm/mach-exynos/dev-sysmmu.c |6 +-
 arch/arm/mach-exynos/pm_domains.c |   13 +
 2 files changed, 18 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-exynos/dev-sysmmu.c 
b/arch/arm/mach-exynos/dev-sysmmu.c
index c5b1ea3..3544638 100644
--- a/arch/arm/mach-exynos/dev-sysmmu.c
+++ b/arch/arm/mach-exynos/dev-sysmmu.c
@@ -271,4 +271,8 @@ static int __init init_sysmmu_platform_device(void)
 
return 0;
 }
-arch_initcall(init_sysmmu_platform_device);
+/*
+ * SYSMMU platform devices must be registered before power domains
+ * see pm_domain.c, which use arch_initcall()
+ */
+core_initcall(init_sysmmu_platform_device);
diff --git a/arch/arm/mach-exynos/pm_domains.c 
b/arch/arm/mach-exynos/pm_domains.c
index 13b3068..51a028d 100644
--- a/arch/arm/mach-exynos/pm_domains.c
+++ b/arch/arm/mach-exynos/pm_domains.c
@@ -21,6 +21,7 @@
 #include linux/of_address.h
 
 #include mach/regs-pmu.h
+#include mach/sysmmu.h
 #include plat/devs.h
 
 /*
@@ -155,6 +156,18 @@ static __init int exynos4_pm_init_power_domain(void)
pm_genpd_init(exynos4_pm_domains[idx]-pd, NULL,
exynos4_pm_domains[idx]-is_off);
 
+#ifdef CONFIG_EXYNOS_DEV_SYSMMU
+   exynos_pm_add_dev_to_genpd(SYSMMU_PLATDEV(fimc0), exynos4_pd_cam);
+   exynos_pm_add_dev_to_genpd(SYSMMU_PLATDEV(fimc1), exynos4_pd_cam);
+   exynos_pm_add_dev_to_genpd(SYSMMU_PLATDEV(fimc2), exynos4_pd_cam);
+   exynos_pm_add_dev_to_genpd(SYSMMU_PLATDEV(fimc3), exynos4_pd_cam);
+   exynos_pm_add_dev_to_genpd(SYSMMU_PLATDEV(jpeg), exynos4_pd_cam);
+   exynos_pm_add_dev_to_genpd(SYSMMU_PLATDEV(mfc_l), exynos4_pd_mfc);
+   exynos_pm_add_dev_to_genpd(SYSMMU_PLATDEV(mfc_r), exynos4_pd_mfc);
+   exynos_pm_add_dev_to_genpd(SYSMMU_PLATDEV(fimd0), exynos4_pd_lcd0);
+   exynos_pm_add_dev_to_genpd(SYSMMU_PLATDEV(rot), exynos4_pd_lcd0);
+   exynos_pm_add_dev_to_genpd(SYSMMU_PLATDEV(tv), exynos4_pd_tv);
+#endif
 #ifdef CONFIG_S5P_DEV_FIMD0
exynos_pm_add_dev_to_genpd(s5p_device_fimd0, exynos4_pd_lcd0);
 #endif
-- 
1.7.1.569.g6f426

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH/RFC] ARM: Exynos4: Integrate IOMMU aware DMA-mapping

2012-04-11 Thread Marek Szyprowski
Hi!

This is an example of the IOMMU aware DMA-mapping implementation usage
on a Samsung Exynos4 based NURI board. The ARM DMA-mapping IOMMU aware
implementation is available in the [1] thread: 

This patch essentially registers DMA-mmaping/IOMMU support for FIMC and
MFC devices and performs some tweaks in clocks hierarchy to get SYSMMU
driver working correctly.

The drivers have been tested with mainline V4L2 drivers for FIMC and MFC
hardware.

For easier testing I've created a separate kernel branch with all
required prerequisite patches. It is based on lastest kgene/for-next
branch and is available on my git repository:

git://git.linaro.org/people/mszyprowski/linux-dma-mapping.git 
3.4-rc2-arm-dma-v8-samsung

This patch requires the following items:
1. ARM DMA-mapping patches [1]
2. Exynos SYSMMU driver v12 [2]
3. Exynos SYSMMU driver runtime pm fixes
4. Exynos4 gen_pd power domain driver fixes

Runtime pm and power domain patches are required on Samsung Nuri board,
but might be optional on boards where bootloader doesn't disable all
devices on boot.

[1] http://www.spinics.net/lists/linux-arch/msg17331.html
[2] https://lkml.org/lkml/2012/3/15/51

Best regards
Marek Szyprowski
Samsung Poland RD Center


Patch summary:

Marek Szyprowski (1):
  ARM: Exynos4: integrate SYSMMU driver with DMA-mapping interface

 arch/arm/mach-exynos/Kconfig   |1 +
 arch/arm/mach-exynos/clock-exynos4.c   |   64 +++-
 arch/arm/mach-exynos/dev-sysmmu.c  |   44 +++
 arch/arm/mach-exynos/include/mach/sysmmu.h |3 +
 drivers/iommu/Kconfig  |1 +
 5 files changed, 84 insertions(+), 29 deletions(-)

-- 
1.7.1.569.g6f426

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH] ARM: Exynos4: integrate SYSMMU driver with DMA-mapping interface

2012-04-11 Thread Marek Szyprowski
This patch provides an provides setup code which assigns IOMMU controllers
to FIMC and MFC devices and enables IOMMU aware DMA-mapping for them.
It has been tested on Samsung Exynos4 platform, NURI board.

Most of the work is done in the s5p_sysmmu_late_init() function, which
first assigns SYSMMU controller to respective client device and then
creates IO address space mapping structures. In this example 128 MiB of
address space is created at 0x2000 for most of the devices. IO address
allocation precision is set to 2^4 pages, so all small allocations will be
aligned to 64 pages. This reduces the size of the io address space bitmap
to 4 KiB.

To solve the clock dependency issues, parent clocks have been added to each
SYSMMU controller bus clock. This models the true hardware behavior,
because client's device bus clock also gates the respective sysmmu bus
clock.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
Acked-by: Kyungmin Park kyungmin.p...@samsung.com
---
 arch/arm/mach-exynos/Kconfig   |1 +
 arch/arm/mach-exynos/clock-exynos4.c   |   64 +++-
 arch/arm/mach-exynos/dev-sysmmu.c  |   44 +++
 arch/arm/mach-exynos/include/mach/sysmmu.h |3 +
 drivers/iommu/Kconfig  |1 +
 5 files changed, 84 insertions(+), 29 deletions(-)

diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 801c738..25b9ba5 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -288,6 +288,7 @@ config MACH_NURI
select S5P_DEV_USB_EHCI
select S5P_SETUP_MIPIPHY
select EXYNOS4_DEV_DMA
+   select EXYNOS_DEV_SYSMMU
select EXYNOS4_SETUP_FIMC
select EXYNOS4_SETUP_FIMD0
select EXYNOS4_SETUP_I2C1
diff --git a/arch/arm/mach-exynos/clock-exynos4.c 
b/arch/arm/mach-exynos/clock-exynos4.c
index 29ae4df..fe459a3 100644
--- a/arch/arm/mach-exynos/clock-exynos4.c
+++ b/arch/arm/mach-exynos/clock-exynos4.c
@@ -497,29 +497,6 @@ static struct clk *exynos4_gate_clocks[] = {
 
 static struct clk exynos4_init_clocks_off[] = {
{
-   .name   = timers,
-   .parent = exynos4_clk_aclk_100.clk,
-   .enable = exynos4_clk_ip_peril_ctrl,
-   .ctrlbit= (124),
-   }, {
-   .name   = csis,
-   .devname= s5p-mipi-csis.0,
-   .enable = exynos4_clk_ip_cam_ctrl,
-   .ctrlbit= (1  4),
-   .parent = exynos4_clk_gate_cam,
-   }, {
-   .name   = csis,
-   .devname= s5p-mipi-csis.1,
-   .enable = exynos4_clk_ip_cam_ctrl,
-   .ctrlbit= (1  5),
-   .parent = exynos4_clk_gate_cam,
-   }, {
-   .name   = jpeg,
-   .id = 0,
-   .enable = exynos4_clk_ip_cam_ctrl,
-   .ctrlbit= (1  6),
-   .parent = exynos4_clk_gate_cam,
-   }, {
.name   = fimc,
.devname= exynos4-fimc.0,
.enable = exynos4_clk_ip_cam_ctrl,
@@ -544,6 +521,35 @@ static struct clk exynos4_init_clocks_off[] = {
.ctrlbit= (1  3),
.parent = exynos4_clk_gate_cam,
}, {
+   .name   = mfc,
+   .devname= s5p-mfc,
+   .enable = exynos4_clk_ip_mfc_ctrl,
+   .ctrlbit= (1  0),
+   .parent = exynos4_clk_gate_mfc,
+   }, {
+   .name   = timers,
+   .parent = exynos4_clk_aclk_100.clk,
+   .enable = exynos4_clk_ip_peril_ctrl,
+   .ctrlbit= (124),
+   }, {
+   .name   = csis,
+   .devname= s5p-mipi-csis.0,
+   .enable = exynos4_clk_ip_cam_ctrl,
+   .ctrlbit= (1  4),
+   .parent = exynos4_clk_gate_cam,
+   }, {
+   .name   = csis,
+   .devname= s5p-mipi-csis.1,
+   .enable = exynos4_clk_ip_cam_ctrl,
+   .ctrlbit= (1  5),
+   .parent = exynos4_clk_gate_cam,
+   }, {
+   .name   = jpeg,
+   .id = 0,
+   .enable = exynos4_clk_ip_cam_ctrl,
+   .ctrlbit= (1  6),
+   .parent = exynos4_clk_gate_cam,
+   }, {
.name   = hsmmc,
.devname= exynos4-sdhci.0,
.parent = exynos4_clk_aclk_133.clk,
@@ -674,12 +680,6 @@ static struct clk exynos4_init_clocks_off[] = {
.ctrlbit= (1  0),
.parent = exynos4_clk_gate_lcd0

RE: [RFC 4/4] drm: Add NVIDIA Tegra support

2012-04-12 Thread Marek Szyprowski
Hi Thierry,

On Thursday, April 12, 2012 9:18 AM Thierry Reding wrote:

 * Arnd Bergmann wrote:
  On Wednesday 11 April 2012, Thierry Reding wrote:
   Daniel Vetter wrote:
Well, you use the iommu api to map/unmap memory into the iommu for 
tegra,
whereas usually device drivers just use the dma api to do that. The 
usual
interface is dma_map_sg/dma_unmap_sg, but there are quite a few variants
around. I'm just wondering why this you've choosen this.
  
   I don't think this works on ARM. Maybe I'm not seeing the whole picture 
   but
   judging by a quick look through the kernel tree there aren't any users 
   that
   map DMA memory through an IOMMU.
 
  dma_map_sg is certainly the right interface to use, and Marek Szyprowski has
  patches to make that work on ARM, hopefully going into v3.5, so you could
  use those.
 
 I've looked at Marek's patches but I don't think they'll work for Tegra 2 or
 Tegra 3. The corresponding iommu_map() functions only set one PTE, regardless
 of the number of bytes passed to them. However, the Tegra TRM indicates that
 mapping needs to be done on a per-page basis so contiguous regions cannot be
 combined. I suppose the IOMMU driver would have to be fixed to program more
 than a single page in that case.

I assume you want to map a set of pages into contiguous chunk in io address 
space.
This can be done with dma_map_sg() call once IOMMU aware implementation has been
assigned to the given device. DMA-mapping implementation is able to merge 
consecutive chunks of the scatter list in the dma/io address space if possible
(i.e. there are no in-page offsets between the chunks). With my implementation 
of IOMMU aware dma-mapping you usually you get a single DMA chunk from the 
provided scatter-list.

I know that this approach causes a lot of confusion at the first look, but that
how dma mapping api has been designed. The scatter list based approach has some
drawbacks - it is a bit oversized for most of the typical use cases for the 
gfx/multimedia buffers, but that's all we have now. 

Scatter lists were initially designed for the disk based block io operations, 
hence the presence of the in-page offsets and lengths for each chunk. For 
multimedia use cases providing an array of struct pages and asking dma-mapping 
to map them into contiguous memory is probably all we need. I wonder if 
introducing such new calls is a good idea. Anrd, what do think? It will 
definitely simplify the drivers and improve the code understanding. On the 
other hand it requires a significant amount of work in the dma-mapping 
framework for all architectures, but that's not a big issue for me.

 Also this doesn't yet solve the vmap() problem that is needed for the kernel
 virtual mapping. I did try using dma_alloc_writecombine(), but that only
 works for chunks of 2 MB or smaller, unless I use init_consistent_dma_size()
 during board setup, which isn't provided for in a DT setup. I couldn't find
 a better alternative, but I admit I'm not very familiar with all the VM APIs.
 Do you have any suggestions on how to solve this? Otherwise I'll try and dig
 in some more.

Yes, I'm aware of this issue I'm currently working on solving it. I hope to use 
standard vmalloc range for all coherent/writecombine allocations and get rid of
the custom 'consistent_dma' region at all.

Best regards
-- 
Marek Szyprowski
Samsung Poland RD Center


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


RE: [PATCH] ARM: Exynos4: integrate SYSMMU driver with DMA-mapping interface

2012-04-12 Thread Marek Szyprowski
Hi Subash,

On Thursday, April 12, 2012 11:06 AM Subash Patel wrote:

 On 04/11/2012 08:06 PM, Marek Szyprowski wrote:
  This patch provides an provides setup code which assigns IOMMU controllers
  to FIMC and MFC devices and enables IOMMU aware DMA-mapping for them.
  It has been tested on Samsung Exynos4 platform, NURI board.
 
  Most of the work is done in the s5p_sysmmu_late_init() function, which
  first assigns SYSMMU controller to respective client device and then
  creates IO address space mapping structures. In this example 128 MiB of
  address space is created at 0x2000 for most of the devices. IO address
  allocation precision is set to 2^4 pages, so all small allocations will be
  aligned to 64 pages. This reduces the size of the io address space bitmap
  to 4 KiB.
 
  To solve the clock dependency issues, parent clocks have been added to each
  SYSMMU controller bus clock. This models the true hardware behavior,
  because client's device bus clock also gates the respective sysmmu bus
  clock.
 
  Signed-off-by: Marek Szyprowskim.szyprow...@samsung.com
  Acked-by: Kyungmin Parkkyungmin.p...@samsung.com
  ---
arch/arm/mach-exynos/Kconfig   |1 +
arch/arm/mach-exynos/clock-exynos4.c   |   64 
  +++-
arch/arm/mach-exynos/dev-sysmmu.c  |   44 +++
arch/arm/mach-exynos/include/mach/sysmmu.h |3 +
drivers/iommu/Kconfig  |1 +
5 files changed, 84 insertions(+), 29 deletions(-)
 
  diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
  index 801c738..25b9ba5 100644
  --- a/arch/arm/mach-exynos/Kconfig
  +++ b/arch/arm/mach-exynos/Kconfig
  @@ -288,6 +288,7 @@ config MACH_NURI
  select S5P_DEV_USB_EHCI
  select S5P_SETUP_MIPIPHY
  select EXYNOS4_DEV_DMA
  +   select EXYNOS_DEV_SYSMMU
  select EXYNOS4_SETUP_FIMC
  select EXYNOS4_SETUP_FIMD0
  select EXYNOS4_SETUP_I2C1
  diff --git a/arch/arm/mach-exynos/clock-exynos4.c 
  b/arch/arm/mach-exynos/clock-exynos4.c
  index 29ae4df..fe459a3 100644
  --- a/arch/arm/mach-exynos/clock-exynos4.c
  +++ b/arch/arm/mach-exynos/clock-exynos4.c
  @@ -497,29 +497,6 @@ static struct clk *exynos4_gate_clocks[] = {
 
static struct clk exynos4_init_clocks_off[] = {
  {
  -   .name   = timers,
  -   .parent =exynos4_clk_aclk_100.clk,
  -   .enable = exynos4_clk_ip_peril_ctrl,
  -   .ctrlbit= (124),
  -   }, {
  -   .name   = csis,
  -   .devname= s5p-mipi-csis.0,
  -   .enable = exynos4_clk_ip_cam_ctrl,
  -   .ctrlbit= (1  4),
  -   .parent =exynos4_clk_gate_cam,
  -   }, {
  -   .name   = csis,
  -   .devname= s5p-mipi-csis.1,
  -   .enable = exynos4_clk_ip_cam_ctrl,
  -   .ctrlbit= (1  5),
  -   .parent =exynos4_clk_gate_cam,
  -   }, {
  -   .name   = jpeg,
  -   .id = 0,
  -   .enable = exynos4_clk_ip_cam_ctrl,
  -   .ctrlbit= (1  6),
  -   .parent =exynos4_clk_gate_cam,
  -   }, {
  .name   = fimc,
  .devname= exynos4-fimc.0,
  .enable = exynos4_clk_ip_cam_ctrl,
  @@ -544,6 +521,35 @@ static struct clk exynos4_init_clocks_off[] = {
  .ctrlbit= (1  3),
  .parent =exynos4_clk_gate_cam,
  }, {
  +   .name   = mfc,
  +   .devname= s5p-mfc,
  +   .enable = exynos4_clk_ip_mfc_ctrl,
  +   .ctrlbit= (1  0),
  +   .parent =exynos4_clk_gate_mfc,
  +   }, {
  +   .name   = timers,
  +   .parent =exynos4_clk_aclk_100.clk,
  +   .enable = exynos4_clk_ip_peril_ctrl,
  +   .ctrlbit= (124),
  +   }, {
  +   .name   = csis,
  +   .devname= s5p-mipi-csis.0,
  +   .enable = exynos4_clk_ip_cam_ctrl,
  +   .ctrlbit= (1  4),
  +   .parent =exynos4_clk_gate_cam,
  +   }, {
  +   .name   = csis,
  +   .devname= s5p-mipi-csis.1,
  +   .enable = exynos4_clk_ip_cam_ctrl,
  +   .ctrlbit= (1  5),
  +   .parent =exynos4_clk_gate_cam,
  +   }, {
  +   .name   = jpeg,
  +   .id = 0,
  +   .enable = exynos4_clk_ip_cam_ctrl,
  +   .ctrlbit= (1  6),
  +   .parent =exynos4_clk_gate_cam,
  +   }, {
  .name   = hsmmc,
  .devname= exynos4-sdhci.0,
  .parent =exynos4_clk_aclk_133.clk,
  @@ -674,12 +680,6 @@ static struct clk exynos4_init_clocks_off[] = {
  .ctrlbit= (1  0

RE: [PATCHv8 10/10] ARM: dma-mapping: add support for IOMMU mapper

2012-04-12 Thread Marek Szyprowski
Hi Arnd,

On Tuesday, April 10, 2012 1:58 PM Arnd Bergmann wrote:

 On Tuesday 10 April 2012, Marek Szyprowski wrote:
  +/**
  + * arm_iommu_create_mapping
  + * @bus: pointer to the bus holding the client device (for IOMMU calls)
  + * @base: start address of the valid IO address space
  + * @size: size of the valid IO address space
  + * @order: accuracy of the IO addresses allocations
  + *
  + * Creates a mapping structure which holds information about used/unused
  + * IO address ranges, which is required to perform memory allocation and
  + * mapping with IOMMU aware functions.
  + *
  + * The client device need to be attached to the mapping with
  + * arm_iommu_attach_device function.
  + */
  +struct dma_iommu_mapping *
  +arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t 
  size,
  +int order)
  +{
  +   unsigned int count = size  (PAGE_SHIFT + order);
  +   unsigned int bitmap_size = BITS_TO_LONGS(count) * sizeof(long);
  +   struct dma_iommu_mapping *mapping;
  +   int err = -ENOMEM;
  +
  +   if (!count)
  +   return ERR_PTR(-EINVAL);
  +
  +   mapping = kzalloc(sizeof(struct dma_iommu_mapping), GFP_KERNEL);
  +   if (!mapping)
  +   goto err;
  +
  +   mapping-bitmap = kzalloc(bitmap_size, GFP_KERNEL);
  +   if (!mapping-bitmap)
  +   goto err2;
  +
  +   mapping-base = base;
  +   mapping-bits = BITS_PER_BYTE * bitmap_size;
  +   mapping-order = order;
  +   spin_lock_init(mapping-lock);
  +
  +   mapping-domain = iommu_domain_alloc(bus);
  +   if (!mapping-domain)
  +   goto err3;
  +
  +   kref_init(mapping-kref);
  +   return mapping;
  +err3:
  +   kfree(mapping-bitmap);
  +err2:
  +   kfree(mapping);
  +err:
  +   return ERR_PTR(err);
  +}
  +EXPORT_SYMBOL(arm_iommu_create_mapping);
 
 I don't understand this function, mostly I guess because you have not
 provided any users. A few questions here:
 
 * What is ARM specific about it that it is named arm_iommu_create_mapping?
   Isn't this completely generic, at least on the interface side?

This function is quite generic. It creates 'struct dma_iommu_mapping' object,
which is stored in the client's device arch data. This object mainly stores
information about io/dma address space: base address, allocation bitmap and
respective iommu domain. Please note that more than one device can be assigned
to the given dma_iommu_mapping to match different hardware topologies.

This function is called by the board/(sub-)platform startup code to initialize
iommu based dma-mapping. For the example usage please refer to 
s5p_create_iommu_mapping() function in arch/arm/mach-exynos/dev-sysmmu.c on 
3.4-rc2-arm-dma-v8-samsung branch in 
git://git.linaro.org/people/mszyprowski/linux-dma-mapping.git

GITWeb shortcut: 
http://git.linaro.org/gitweb?p=people/mszyprowski/linux-dma-mapping.git;a=blob;f=arch/arm/mach-exyno
s/dev-sysmmu.c;h=31f2d6caf0e9949def18abd18af3f9d16737ae19;hb=6025093750d41f88406042e6486e331b806dc87
5#l283

 * Why is this exported to modules? Which device drivers do you expect
   to call it?

I thought it might be useful to use modules for registering devices, but 
now I see that no platform use such approach. I will drop these exports 
unless someone finds a real use case for them.

 * Why do you pass the bus_type in here? That seems like the completely
   wrong thing to do when all devices are on the same bus type (e.g.
   amba or platform) but are connected to different instances that each
   have their own iommu. I guess this is a question for Jörg, because the
   base iommu interface provides iommu_domain_alloc().

That's only a consequence of the iommu api. I would also prefer to use client 
device pointer here instead of the bus id, but maybe I don't have enough 
knowledge about desktop IOMMUs. I suspect that there is also a need to assign
one IOMMU driver to the whole bus (like pci bus) and it originates from such
systems. In embedded world we usually have only one iommu driver which 
operates on the platform bus devices. On Samsung Exynos4 we have over a dozen
SYSMMU controllers for various multimedia blocks, but they are all exactly 
the same. We use one iommu ops structure and store a pointer to the real 
iommu controller instance inside arch data of the client struct device.
 
Best regards
-- 
Marek Szyprowski
Samsung Poland RD Center


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


RE: [PATCH] ARM: Exynos4: integrate SYSMMU driver with DMA-mapping interface

2012-04-12 Thread Marek Szyprowski




 -Original Message-
 From: Arnd Bergmann [mailto:a...@arndb.de]
 Sent: Thursday, April 12, 2012 1:09 PM
 To: Marek Szyprowski
 Cc: 'Subash Patel'; linux-arm-ker...@lists.infradead.org; 
 linaro-mm-...@lists.linaro.org;
 linux...@kvack.org; linux-a...@vger.kernel.org; 
 iommu@lists.linux-foundation.org; 'Kyungmin
 Park'; 'Joerg Roedel'; 'Russell King - ARM Linux'; 'Chunsang Jeong'; 'Krishna 
 Reddy'; 'KyongHo
 Cho'; Andrzej Pietrasiewicz; 'Benjamin Herrenschmidt'; 'Konrad Rzeszutek 
 Wilk'; 'Hiroshi Doyu'
 Subject: Re: [PATCH] ARM: Exynos4: integrate SYSMMU driver with DMA-mapping 
 interface
 
 On Thursday 12 April 2012, Marek Szyprowski wrote:
  +
+/*
+ * s5p_sysmmu_late_init
+ * Create DMA-mapping IOMMU context for specified devices. This 
function must
+ * be called later, once SYSMMU driver gets registered and probed.
+ */
+static int __init s5p_sysmmu_late_init(void)
+{
+   
platform_set_sysmmu(SYSMMU_PLATDEV(fimc0).dev,s5p_device_fimc0.dev);
+   
platform_set_sysmmu(SYSMMU_PLATDEV(fimc1).dev,s5p_device_fimc1.dev);
+   
platform_set_sysmmu(SYSMMU_PLATDEV(fimc2).dev,s5p_device_fimc2.dev);
+   
platform_set_sysmmu(SYSMMU_PLATDEV(fimc3).dev,s5p_device_fimc3.dev);
+   
platform_set_sysmmu(SYSMMU_PLATDEV(mfc_l).dev,s5p_device_mfc_l.dev);
+   
platform_set_sysmmu(SYSMMU_PLATDEV(mfc_r).dev,s5p_device_mfc_r.dev);
+
+   s5p_create_iommu_mapping(s5p_device_fimc0.dev, 0x2000, 
SZ_128M, 4);
+   s5p_create_iommu_mapping(s5p_device_fimc1.dev, 0x2000, 
SZ_128M, 4);
+   s5p_create_iommu_mapping(s5p_device_fimc2.dev, 0x2000, 
SZ_128M, 4);
+   s5p_create_iommu_mapping(s5p_device_fimc3.dev, 0x2000, 
SZ_128M, 4);
+   s5p_create_iommu_mapping(s5p_device_mfc_l.dev, 0x2000, 
SZ_128M, 4);
+   s5p_create_iommu_mapping(s5p_device_mfc_r.dev, 0x4000, 
SZ_128M, 4);
+
+   return 0;
+}
+device_initcall(s5p_sysmmu_late_init);
  
   Shouldn't these things be specific to a SoC? With this RFC, it happens
   that you will predefine the IOMMU attachment and mapping information for
   devices in common location (dev-sysmmu.c)? This may lead to problems
   because there are some IP's with SYSMMU support in exynos5, but not
   available in exynos4 (eg: GSC, FIMC-LITE, FIMC-ISP) Previously we used
   to do above declaration in individual machine file, which I think was
   more meaningful.
 
  Right, I simplified the code too much. Keeping these definitions inside 
  machine
  files was a better idea. I completely forgot that Exynos sub-platform now 
  covers
  both Exynos4 and Exynos5 SoC families.
 
 Ideally the information about iommu attachment should come from the
 device tree. We have the dma-ranges properties that define how a dma
 address space is mapped. I am not entirely sure how that works when you
 have multiple IOMMUs and if that requires defining addititional properties,
 but I think we should make it so that we don't have to hardcode specific
 devices in the source.

Right, until that time machine/board files are imho ok.

Best regards
-- 
Marek Szyprowski
Samsung Poland RD Center


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


RE: [PATCH 2/2] ARM: Exynos4: update SYSMMU setup code for gen_pd power domain driver

2012-04-16 Thread Marek Szyprowski
Hi,

On Monday, April 16, 2012 12:10 PM KyongHo Cho wrote:

 On Wed, Apr 11, 2012 at 11:34 PM, Marek Szyprowski
 m.szyprow...@samsung.com wrote:
  SYSMMU platform devices must be registered before setting up power
  domains to let power domain driver to correctly register also SYSMMU
  controller devices. This patch also registers SYSMMU controller devices
  to respective power domains.
 
  Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
  Acked-by: Kyungmin Park kyungmin.p...@samsung.com
  ---
   arch/arm/mach-exynos/dev-sysmmu.c |    6 +-
   arch/arm/mach-exynos/pm_domains.c |   13 +
   2 files changed, 18 insertions(+), 1 deletions(-)
 
  diff --git a/arch/arm/mach-exynos/dev-sysmmu.c 
  b/arch/arm/mach-exynos/dev-sysmmu.c
  index c5b1ea3..3544638 100644
  --- a/arch/arm/mach-exynos/dev-sysmmu.c
  +++ b/arch/arm/mach-exynos/dev-sysmmu.c
  @@ -271,4 +271,8 @@ static int __init init_sysmmu_platform_device(void)
 
         return 0;
   }
  -arch_initcall(init_sysmmu_platform_device);
  +/*
  + * SYSMMU platform devices must be registered before power domains
  + * see pm_domain.c, which use arch_initcall()
  + */
  +core_initcall(init_sysmmu_platform_device);
 I don't understand why init_sysmmu_platform_device() must be called before
 exynos4_pm_init_power_domain()?
 
 Other devices also added by an arch_initcall() function which calls
 mdesc-init_machine().
 I also was unable to find any reason to add devices before registering
 the devices to pm domain.

mdesc-init_machine is called before exynos4_pm_init_power_domain() from 
arch/arm/mach-exynos/pm_domain.c, although both are started from arch_initcall.
In this case the order of linking defines the order of calls.

exynos4_pm_init_power_domain() calls exynos_pm_add_dev_to_genpd() which in turn
checks for pdev-dev.bus. All devices which have not been registered yet on the
bus are simply skipped.

Best regards
-- 
Marek Szyprowski
Samsung Poland RD Center


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCHv9 02/10] ARM: dma-mapping: use pr_* instread of printk

2012-04-18 Thread Marek Szyprowski
Replace all calls to printk with pr_* functions family.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
Acked-by: Kyungmin Park kyungmin.p...@samsung.com
Acked-by: Arnd Bergmann a...@arndb.de
Tested-By: Subash Patel subash.ramasw...@linaro.org
---
 arch/arm/mm/dma-mapping.c |   16 
 1 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index db23ae4..366f3a2 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -184,14 +184,14 @@ static int __init consistent_init(void)
 
pud = pud_alloc(init_mm, pgd, base);
if (!pud) {
-   printk(KERN_ERR %s: no pud tables\n, __func__);
+   pr_err(%s: no pud tables\n, __func__);
ret = -ENOMEM;
break;
}
 
pmd = pmd_alloc(init_mm, pud, base);
if (!pmd) {
-   printk(KERN_ERR %s: no pmd tables\n, __func__);
+   pr_err(%s: no pmd tables\n, __func__);
ret = -ENOMEM;
break;
}
@@ -199,7 +199,7 @@ static int __init consistent_init(void)
 
pte = pte_alloc_kernel(pmd, base);
if (!pte) {
-   printk(KERN_ERR %s: no pte tables\n, __func__);
+   pr_err(%s: no pte tables\n, __func__);
ret = -ENOMEM;
break;
}
@@ -222,7 +222,7 @@ __dma_alloc_remap(struct page *page, size_t size, gfp_t 
gfp, pgprot_t prot,
int bit;
 
if (!consistent_pte) {
-   printk(KERN_ERR %s: not initialised\n, __func__);
+   pr_err(%s: not initialised\n, __func__);
dump_stack();
return NULL;
}
@@ -281,14 +281,14 @@ static void __dma_free_remap(void *cpu_addr, size_t size)
 
c = arm_vmregion_find_remove(consistent_head, (unsigned long)cpu_addr);
if (!c) {
-   printk(KERN_ERR %s: trying to free invalid coherent area: 
%p\n,
+   pr_err(%s: trying to free invalid coherent area: %p\n,
   __func__, cpu_addr);
dump_stack();
return;
}
 
if ((c-vm_end - c-vm_start) != size) {
-   printk(KERN_ERR %s: freeing wrong coherent size (%ld != %d)\n,
+   pr_err(%s: freeing wrong coherent size (%ld != %d)\n,
   __func__, c-vm_end - c-vm_start, size);
dump_stack();
size = c-vm_end - c-vm_start;
@@ -310,8 +310,8 @@ static void __dma_free_remap(void *cpu_addr, size_t size)
}
 
if (pte_none(pte) || !pte_present(pte))
-   printk(KERN_CRIT %s: bad page in kernel page table\n,
-  __func__);
+   pr_crit(%s: bad page in kernel page table\n,
+   __func__);
} while (size -= PAGE_SIZE);
 
flush_tlb_kernel_range(c-vm_start, c-vm_end);
-- 
1.7.1.569.g6f426

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCHv9 08/10] ARM: dma-mapping: remove redundant code and cleanup

2012-04-18 Thread Marek Szyprowski
This patch just performs a global cleanup in DMA mapping implementation
for ARM architecture. Some of the tiny helper functions have been moved
to the caller code, some have been merged together.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
Acked-by: Kyungmin Park kyungmin.p...@samsung.com
Acked-by: Arnd Bergmann a...@arndb.de
Tested-By: Subash Patel subash.ramasw...@linaro.org
---
 arch/arm/mm/dma-mapping.c |   88 
 1 files changed, 24 insertions(+), 64 deletions(-)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index a4db5ec..615fabd 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -40,64 +40,12 @@
  * the CPU does do speculative prefetches, which means we clean caches
  * before transfers and delay cache invalidation until transfer completion.
  *
- * Private support functions: these are not part of the API and are
- * liable to change.  Drivers must not use these.
  */
-static inline void __dma_single_cpu_to_dev(const void *kaddr, size_t size,
-   enum dma_data_direction dir)
-{
-   extern void ___dma_single_cpu_to_dev(const void *, size_t,
-   enum dma_data_direction);
-
-   if (!arch_is_coherent())
-   ___dma_single_cpu_to_dev(kaddr, size, dir);
-}
-
-static inline void __dma_single_dev_to_cpu(const void *kaddr, size_t size,
-   enum dma_data_direction dir)
-{
-   extern void ___dma_single_dev_to_cpu(const void *, size_t,
-   enum dma_data_direction);
-
-   if (!arch_is_coherent())
-   ___dma_single_dev_to_cpu(kaddr, size, dir);
-}
-
-static inline void __dma_page_cpu_to_dev(struct page *page, unsigned long off,
-   size_t size, enum dma_data_direction dir)
-{
-   extern void ___dma_page_cpu_to_dev(struct page *, unsigned long,
+static void __dma_page_cpu_to_dev(struct page *, unsigned long,
size_t, enum dma_data_direction);
-
-   if (!arch_is_coherent())
-   ___dma_page_cpu_to_dev(page, off, size, dir);
-}
-
-static inline void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
-   size_t size, enum dma_data_direction dir)
-{
-   extern void ___dma_page_dev_to_cpu(struct page *, unsigned long,
+static void __dma_page_dev_to_cpu(struct page *, unsigned long,
size_t, enum dma_data_direction);
 
-   if (!arch_is_coherent())
-   ___dma_page_dev_to_cpu(page, off, size, dir);
-}
-
-
-static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
-unsigned long offset, size_t size, enum dma_data_direction dir)
-{
-   __dma_page_cpu_to_dev(page, offset, size, dir);
-   return pfn_to_dma(dev, page_to_pfn(page)) + offset;
-}
-
-static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
-   size_t size, enum dma_data_direction dir)
-{
-   __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
-   handle  ~PAGE_MASK, size, dir);
-}
-
 /**
  * arm_dma_map_page - map a portion of a page for streaming DMA
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
@@ -112,11 +60,13 @@ static inline void __dma_unmap_page(struct device *dev, 
dma_addr_t handle,
  * The device owns this memory once this call has completed.  The CPU
  * can regain ownership by calling dma_unmap_page().
  */
-static inline dma_addr_t arm_dma_map_page(struct device *dev, struct page 
*page,
+static dma_addr_t arm_dma_map_page(struct device *dev, struct page *page,
 unsigned long offset, size_t size, enum dma_data_direction dir,
 struct dma_attrs *attrs)
 {
-   return __dma_map_page(dev, page, offset, size, dir);
+   if (!arch_is_coherent())
+   __dma_page_cpu_to_dev(page, offset, size, dir);
+   return pfn_to_dma(dev, page_to_pfn(page)) + offset;
 }
 
 /**
@@ -133,27 +83,31 @@ static inline dma_addr_t arm_dma_map_page(struct device 
*dev, struct page *page,
  * After this call, reads by the CPU to the buffer are guaranteed to see
  * whatever the device wrote there.
  */
-static inline void arm_dma_unmap_page(struct device *dev, dma_addr_t handle,
+static void arm_dma_unmap_page(struct device *dev, dma_addr_t handle,
size_t size, enum dma_data_direction dir,
struct dma_attrs *attrs)
 {
-   __dma_unmap_page(dev, handle, size, dir);
+   if (!arch_is_coherent())
+   __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
+ handle  ~PAGE_MASK, size, dir);
 }
 
-static inline void arm_dma_sync_single_for_cpu(struct device *dev,
+static void arm_dma_sync_single_for_cpu(struct device *dev,
dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
unsigned int offset = handle  (PAGE_SIZE - 1);
struct page *page = pfn_to_page(dma_to_pfn(dev, handle-offset));
-   __dma_page_dev_to_cpu(page, offset, size, dir

[PATCHv9 00/10] ARM: DMA-mapping framework redesign

2012-04-18 Thread Marek Szyprowski
Hello,

This is a quick update on dma-mapping redesign patches for ARM. I did
some minor fixes suggested by Arnd and extended commit messages for a
few patches. Like the previous version, the patches have been rebased 
onto latest Linux v3.4-rc3 which comes with dma_map_ops related
preparation changes.

The patches are also available on my git repository at:
git://git.linaro.org/people/mszyprowski/linux-dma-mapping.git 3.4-rc3-arm-dma-v9

The code has been tested on Samsung Exynos4 'UniversalC210' and NURI
boards with IOMMU driver posted by KyongHo Cho. The integration patch
has been posted in the following thread:
http://www.spinics.net/lists/arm-kernel/msg169030.html


History of the development:

v1: (initial version of the DMA-mapping redesign patches):
http://www.spinics.net/lists/linux-mm/msg21241.html

v2:
http://lists.linaro.org/pipermail/linaro-mm-sig/2011-September/000571.html
http://lists.linaro.org/pipermail/linaro-mm-sig/2011-September/000577.html

v3:
http://www.spinics.net/lists/linux-mm/msg25490.html

v4 and v5:
http://www.spinics.net/lists/arm-kernel/msg151147.html
http://www.spinics.net/lists/arm-kernel/msg154889.html

v6:
http://www.spinics.net/lists/linux-mm/msg29903.html

v7:
http://www.spinics.net/lists/arm-kernel/msg162149.html

v8:
http://www.spinics.net/lists/arm-kernel/msg168478.html

Best regards
Marek Szyprowski
Samsung Poland RD Center


Patch summary:

Marek Szyprowski (10):
  common: add dma_mmap_from_coherent() function
  ARM: dma-mapping: use pr_* instread of printk
  ARM: dma-mapping: introduce DMA_ERROR_CODE constant
  ARM: dma-mapping: remove offset parameter to prepare for generic
dma_ops
  ARM: dma-mapping: use asm-generic/dma-mapping-common.h
  ARM: dma-mapping: implement dma sg methods on top of any generic dma
ops
  ARM: dma-mapping: move all dma bounce code to separate dma ops
structure
  ARM: dma-mapping: remove redundant code and cleanup
  ARM: dma-mapping: use alloc, mmap, free from dma_ops
  ARM: dma-mapping: add support for IOMMU mapper

 arch/arm/Kconfig   |9 +
 arch/arm/common/dmabounce.c|   84 +++-
 arch/arm/include/asm/device.h  |4 +
 arch/arm/include/asm/dma-iommu.h   |   34 ++
 arch/arm/include/asm/dma-mapping.h |  407 ---
 arch/arm/mm/dma-mapping.c  | 1015 ++--
 arch/arm/mm/vmregion.h |2 +-
 drivers/base/dma-coherent.c|   42 ++
 include/asm-generic/dma-coherent.h |4 +-
 9 files changed, 1134 insertions(+), 467 deletions(-)
 create mode 100644 arch/arm/include/asm/dma-iommu.h

-- 
1.7.1.569.g6f426

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCHv10 00/11] ARM: DMA-mapping framework redesign

2012-05-17 Thread Marek Szyprowski
Hello,

This is another update on dma-mapping redesign patches for ARM. I
integrated a few minor fixes that were needed to solve the issues
reported after putting these patches for testing in linux-next branch.

The patches are also available on my git repository at:
git://git.linaro.org/people/mszyprowski/linux-dma-mapping.git 
3.4-rc7-arm-dma-v10

History of the development:

v1: (initial version of the DMA-mapping redesign patches):
http://www.spinics.net/lists/linux-mm/msg21241.html

v2:
http://lists.linaro.org/pipermail/linaro-mm-sig/2011-September/000571.html
http://lists.linaro.org/pipermail/linaro-mm-sig/2011-September/000577.html

v3:
http://www.spinics.net/lists/linux-mm/msg25490.html

v4 and v5:
http://www.spinics.net/lists/arm-kernel/msg151147.html
http://www.spinics.net/lists/arm-kernel/msg154889.html

v6:
http://www.spinics.net/lists/linux-mm/msg29903.html

v7:
http://www.spinics.net/lists/arm-kernel/msg162149.html

v8:
http://www.spinics.net/lists/arm-kernel/msg168478.html

v9:
http://www.spinics.net/lists/linux-arch/msg17443.html

Best regards
Marek Szyprowski
Samsung Poland RD Center


Patch summary:

Marek Szyprowski (11):
  common: add dma_mmap_from_coherent() function
  ARM: dma-mapping: use dma_mmap_from_coherent()
  ARM: dma-mapping: use pr_* instread of printk
  ARM: dma-mapping: introduce DMA_ERROR_CODE constant
  ARM: dma-mapping: remove offset parameter to prepare for generic
dma_ops
  ARM: dma-mapping: use asm-generic/dma-mapping-common.h
  ARM: dma-mapping: implement dma sg methods on top of any generic dma
ops
  ARM: dma-mapping: move all dma bounce code to separate dma ops
structure
  ARM: dma-mapping: remove redundant code and do the cleanup
  ARM: dma-mapping: use alloc, mmap, free from dma_ops
  ARM: dma-mapping: add support for IOMMU mapper

 arch/arm/Kconfig   |9 +
 arch/arm/common/dmabounce.c|   84 ++-
 arch/arm/include/asm/device.h  |4 +
 arch/arm/include/asm/dma-iommu.h   |   34 ++
 arch/arm/include/asm/dma-mapping.h |  407 ---
 arch/arm/mm/dma-mapping.c  | 1015 ++--
 arch/arm/mm/vmregion.h |2 +-
 drivers/base/dma-coherent.c|   42 ++
 include/asm-generic/dma-coherent.h |4 +-
 9 files changed, 1134 insertions(+), 467 deletions(-)
 create mode 100644 arch/arm/include/asm/dma-iommu.h

-- 
1.7.10.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCHv10 02/11] ARM: dma-mapping: use dma_mmap_from_coherent()

2012-05-17 Thread Marek Szyprowski
Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 arch/arm/mm/dma-mapping.c |3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index db23ae4..7ec0863 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -401,6 +401,9 @@ static int dma_mmap(struct device *dev, struct 
vm_area_struct *vma,
unsigned long user_size, kern_size;
struct arm_vmregion *c;
 
+   if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, ret))
+   return ret;
+
user_size = (vma-vm_end - vma-vm_start)  PAGE_SHIFT;
 
c = arm_vmregion_find(consistent_head, (unsigned long)cpu_addr);
-- 
1.7.10.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCHv10 04/11] ARM: dma-mapping: introduce DMA_ERROR_CODE constant

2012-05-17 Thread Marek Szyprowski
Replace all uses of ~0 with DMA_ERROR_CODE, what should make the code
easier to read.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
Acked-by: Kyungmin Park kyungmin.p...@samsung.com
Tested-By: Subash Patel subash.ramasw...@linaro.org
---
 arch/arm/common/dmabounce.c|6 +++---
 arch/arm/include/asm/dma-mapping.h |4 +++-
 arch/arm/mm/dma-mapping.c  |2 +-
 3 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 595ecd29..210ad1b 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -254,7 +254,7 @@ static inline dma_addr_t map_single(struct device *dev, 
void *ptr, size_t size,
if (buf == NULL) {
dev_err(dev, %s: unable to map unsafe buffer %p!\n,
   __func__, ptr);
-   return ~0;
+   return DMA_ERROR_CODE;
}
 
dev_dbg(dev, %s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n,
@@ -320,7 +320,7 @@ dma_addr_t __dma_map_page(struct device *dev, struct page 
*page,
 
ret = needs_bounce(dev, dma_addr, size);
if (ret  0)
-   return ~0;
+   return DMA_ERROR_CODE;
 
if (ret == 0) {
__dma_page_cpu_to_dev(page, offset, size, dir);
@@ -329,7 +329,7 @@ dma_addr_t __dma_map_page(struct device *dev, struct page 
*page,
 
if (PageHighMem(page)) {
dev_err(dev, DMA buffer bouncing of HIGHMEM pages is not 
supported\n);
-   return ~0;
+   return DMA_ERROR_CODE;
}
 
return map_single(dev, page_address(page) + offset, size, dir);
diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index cb3b7c9..6a838da 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -10,6 +10,8 @@
 #include asm-generic/dma-coherent.h
 #include asm/memory.h
 
+#define DMA_ERROR_CODE (~0)
+
 #ifdef __arch_page_to_dma
 #error Please update to __arch_pfn_to_dma
 #endif
@@ -123,7 +125,7 @@ extern int dma_set_mask(struct device *, u64);
  */
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
-   return dma_addr == ~0;
+   return dma_addr == DMA_ERROR_CODE;
 }
 
 /*
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 322c70a..e4ac5fc 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -342,7 +342,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t 
*handle, gfp_t gfp,
 */
gfp = ~(__GFP_COMP);
 
-   *handle = ~0;
+   *handle = DMA_ERROR_CODE;
size = PAGE_ALIGN(size);
 
page = __dma_alloc_buffer(dev, size, gfp);
-- 
1.7.10.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


RE: How to specify IOMMU'able devices in DT (was: [RFC 0/5] ARM: dma-mapping: New dma_map_ops to control IOVA more precisely)

2012-09-24 Thread Marek Szyprowski
Hello,

On Monday, September 24, 2012 11:45 AM Hiroshi Doyu wrote:

 On Mon, 24 Sep 2012 11:28:01 +0200
 James Bottomley james.bottom...@hansenpartnership.com wrote:
 
  On Mon, 2012-09-24 at 12:04 +0300, Hiroshi Doyu wrote:
   diff --git a/drivers/base/platform.c b/drivers/base/platform.c
   index a1a7225..9eae3be 100644
   --- a/drivers/base/platform.c
   +++ b/drivers/base/platform.c
   @@ -21,6 +21,8 @@
#include linux/slab.h
#include linux/pm_runtime.h
  
   +#include asm/dma-iommu.h
   +
#include base.h
  
#define to_platform_driver(drv)(container_of((drv), struct
   platform_driver, \
   @@ -305,8 +307,19 @@ int platform_device_add(struct platform_device
   *pdev)
dev_name(pdev-dev), dev_name(pdev-dev.parent));
  
   ret = device_add(pdev-dev);
   -   if (ret == 0)
   -   return ret;
   +   if (ret)
   +   goto failed;
   +
   +#ifdef CONFIG_PLATFORM_ENABLE_IOMMU
   +   if (platform_bus_type.map  !pdev-dev.archdata.mapping) {
   +   ret = arm_iommu_attach_device(pdev-dev,
   + platform_bus_type.map);
   +   if (ret)
   +   goto failed;
 
  This is horrible ... you're adding an architecture specific callback
  into our generic code; that's really a no-no.  If the concept of
  CONFIG_PLATFORM_ENABE_IOMMU is useful to more than just arm, then this
  could become a generic callback.
 
 As mentioned in the original, this is a heck to explain what is
 needed. I am looking for some generic solution for how to specify
 IOMMU info for each platform devices. I'm guessing that some other SoC
 may have the similar requirements on the above. As you mentioned, this
 solution should be a generic, not arch specific.

Please read more about bus notifiers. IMHO a good example is provided in 
the following thread:
http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg12238.html

Best regards
-- 
Marek Szyprowski
Samsung Poland RD Center


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 3/9] ARM: dma-mapping: Always pass proper prot flags to iommu_map()

2013-09-30 Thread Marek Szyprowski

Hello,

On 2013-09-27 00:36, Andreas Herrmann wrote:

... otherwise it is impossible for the low level iommu driver to
figure out which pte flags should be used.

In __map_sg_chunk we can derive the flags from dma_data_direction.

In __iommu_create_mapping we should treat the memory like
DMA_BIDIRECTIONAL and pass both IOMMU_READ and IOMMU_WRITE to
iommu_map.
__iommu_create_mapping is used during dma_alloc_coherent (via
arm_iommu_alloc_attrs).  AFAIK dma_alloc_coherent is responsible for
allocation _and_ mapping.  I think this implies that access to the
mapped pages should be allowed.

Cc: Marek Szyprowski m.szyprow...@samsung.com
Signed-off-by: Andreas Herrmann andreas.herrm...@calxeda.com


Thanks pointing the issue and preparing the patch. I will push it to the 
dma-mapping fixes branch.



---
  arch/arm/mm/dma-mapping.c |   43 ---
  1 file changed, 28 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index f5e1a84..1272ed2 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1232,7 +1232,8 @@ __iommu_create_mapping(struct device *dev, struct page 
**pages, size_t size)
break;
  
  		len = (j - i)  PAGE_SHIFT;

-   ret = iommu_map(mapping-domain, iova, phys, len, 0);
+   ret = iommu_map(mapping-domain, iova, phys, len,
+   IOMMU_READ|IOMMU_WRITE);
if (ret  0)
goto fail;
iova += len;
@@ -1431,6 +1432,27 @@ static int arm_iommu_get_sgtable(struct device *dev, 
struct sg_table *sgt,
 GFP_KERNEL);
  }
  
+static int __dma_direction_to_prot(enum dma_data_direction dir)

+{
+   int prot;
+
+   switch (dir) {
+   case DMA_BIDIRECTIONAL:
+   prot = IOMMU_READ | IOMMU_WRITE;
+   break;
+   case DMA_TO_DEVICE:
+   prot = IOMMU_READ;
+   break;
+   case DMA_FROM_DEVICE:
+   prot = IOMMU_WRITE;
+   break;
+   default:
+   prot = 0;
+   }
+
+   return prot;
+}
+
  /*
   * Map a part of the scatter-gather list into contiguous io address space
   */
@@ -1444,6 +1466,7 @@ static int __map_sg_chunk(struct device *dev, struct 
scatterlist *sg,
int ret = 0;
unsigned int count;
struct scatterlist *s;
+   int prot;
  
  	size = PAGE_ALIGN(size);

*handle = DMA_ERROR_CODE;
@@ -1460,7 +1483,9 @@ static int __map_sg_chunk(struct device *dev, struct 
scatterlist *sg,
!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
__dma_page_cpu_to_dev(sg_page(s), s-offset, s-length, 
dir);
  
-		ret = iommu_map(mapping-domain, iova, phys, len, 0);

+   prot = __dma_direction_to_prot(dir);
+
+   ret = iommu_map(mapping-domain, iova, phys, len, prot);
if (ret  0)
goto fail;
count += len  PAGE_SHIFT;
@@ -1665,19 +1690,7 @@ static dma_addr_t arm_coherent_iommu_map_page(struct 
device *dev, struct page *p
if (dma_addr == DMA_ERROR_CODE)
return dma_addr;
  
-	switch (dir) {

-   case DMA_BIDIRECTIONAL:
-   prot = IOMMU_READ | IOMMU_WRITE;
-   break;
-   case DMA_TO_DEVICE:
-   prot = IOMMU_READ;
-   break;
-   case DMA_FROM_DEVICE:
-   prot = IOMMU_WRITE;
-   break;
-   default:
-   prot = 0;
-   }
+   prot = __dma_direction_to_prot(dir);
  
  	ret = iommu_map(mapping-domain, dma_addr, page_to_phys(page), len, prot);

if (ret  0)


Best regards
--
Marek Szyprowski
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v2 1/5] x86: make dma_alloc_coherent() return zeroed memory if CMA is enabled

2014-01-27 Thread Marek Szyprowski

Hello,

On 2014-01-14 15:13, Akinobu Mita wrote:

Calling dma_alloc_coherent() with __GFP_ZERO must return zeroed memory.

But when the contiguous memory allocator (CMA) is enabled on x86 and
the memory region is allocated by dma_alloc_from_contiguous(), it
doesn't return zeroed memory.  Because dma_generic_alloc_coherent()
forgot to fill the memory region with zero if it was allocated by
dma_alloc_from_contiguous()


I just wonder how it will work with high mem? I've didn't check the x86
dma mapping code yet, but page_address() works only for pages, which comes
from low memory. In other patches you have added an option to place CMA
area anywhere in the memory. Is the x86 pci dma code ready for the case
when cma area is put into high mem and direct mappings are not available?


Most implementations of dma_alloc_coherent() return zeroed memory
regardless of whether __GFP_ZERO is specified.  So this fixes it by
unconditionally zeroing the allocated memory region.

Cc: Marek Szyprowski m.szyprow...@samsung.com
Cc: Konrad Rzeszutek Wilk konrad.w...@oracle.com
Cc: David Woodhouse dw...@infradead.org
Cc: Don Dutile ddut...@redhat.com
Cc: Thomas Gleixner t...@linutronix.de
Cc: Ingo Molnar mi...@redhat.com
Cc: H. Peter Anvin h...@zytor.com
Cc: Andi Kleen a...@firstfloor.org
Cc: x...@kernel.org
Cc: iommu@lists.linux-foundation.org
Signed-off-by: Akinobu Mita akinobu.m...@gmail.com
---
New patch from this version

  arch/x86/kernel/pci-dma.c | 3 +--
  1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 872079a..9644405 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -97,7 +97,6 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t 
size,
  
  	dma_mask = dma_alloc_coherent_mask(dev, flag);
  
-	flag |= __GFP_ZERO;

  again:
page = NULL;
if (!(flag  GFP_ATOMIC))
@@ -118,7 +117,7 @@ again:
  
  		return NULL;

}
-
+   memset(page_address(page), 0, size);
*dma_addr = addr;
return page_address(page);
  }


Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 0/2] arm: dma-mapping: add dynamic resize of IOVA bitmap

2014-02-25 Thread Marek Szyprowski
Hello,

This patchset is a continuation of the work started by Andreas Herrmann
to add support for dynamically resized bitmaps for IOMMU based
DMA-mapping implementation for ARM architecture. Some more discussion
and rationale has been discussed in the following thread:
http://www.spinics.net/lists/arm-kernel/msg303732.html

The first patch adds support for on-demand extending IO address space
bitmap. It is based on the original work by Andreas Herrmann, but I
decided to drop arm_iommu_create_mapping() api change part. The second
patch removes the 'order' hack, which was used to reduce the size of a
bitmap. The first patch solved the problem of too large io address space
bitmaps, so the 'order' hack is no longer needed. The parameters of the
arm_iommu_create_mapping() function can be then simplified by dropping
'order' parameter without any functional change of the whole subsystem.
This parameter was already a bit misunderstood, so the overall result is
also a little improvement of the API.

Best regards
Marek Szyprowski, PhD
Samsung RD Institute Poland

Andreas Herrmann (1):
  arm: dma-mapping: Add support to extend DMA IOMMU mappings

Marek Szyprowski (1):
  arm: dma-mapping: remove order parameter from
arm_iommu_create_mapping()

 arch/arm/include/asm/dma-iommu.h  |   12 ++-
 arch/arm/mm/dma-mapping.c |  144 +++--
 drivers/gpu/drm/exynos/exynos_drm_drv.h   |2 -
 drivers/gpu/drm/exynos/exynos_drm_iommu.c |6 +-
 drivers/gpu/drm/exynos/exynos_drm_iommu.h |1 -
 drivers/iommu/shmobile-iommu.c|2 +-
 6 files changed, 124 insertions(+), 43 deletions(-)

-- 
1.7.9.5

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 1/2] arm: dma-mapping: Add support to extend DMA IOMMU mappings

2014-02-25 Thread Marek Szyprowski
From: Andreas Herrmann andreas.herrm...@calxeda.com

Instead of using just one bitmap to keep track of IO virtual addresses
(handed out for IOMMU use) introduce an array of bitmaps. This allows
us to extend existing mappings when running out of iova space in the
initial mapping etc.

If there is not enough space in the mapping to service an IO virtual
address allocation request, __alloc_iova() tries to extend the mapping
-- by allocating another bitmap -- and makes another allocation
attempt using the freshly allocated bitmap.

This allows arm iommu drivers to start with a decent initial size when
an dma_iommu_mapping is created and still to avoid running out of IO
virtual addresses for the mapping.

Signed-off-by: Andreas Herrmann andreas.herrm...@calxeda.com
[mszyprow: removed extensions parameter to arm_iommu_create_mapping()
 function, which will be modified in the next patch anyway, also some
 debug messages about extending bitmap]
Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 arch/arm/include/asm/dma-iommu.h |8 ++-
 arch/arm/mm/dma-mapping.c|  123 --
 2 files changed, 110 insertions(+), 21 deletions(-)

diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h
index a8c56ac..686797c 100644
--- a/arch/arm/include/asm/dma-iommu.h
+++ b/arch/arm/include/asm/dma-iommu.h
@@ -13,8 +13,12 @@ struct dma_iommu_mapping {
/* iommu specific data */
struct iommu_domain *domain;
 
-   void*bitmap;
-   size_t  bits;
+   unsigned long   **bitmaps;  /* array of bitmaps */
+   unsigned intnr_bitmaps; /* nr of elements in array */
+   unsigned intextensions;
+   size_t  bitmap_size;/* size of a single bitmap */
+   size_t  bits;   /* per bitmap */
+   unsigned intsize;   /* per bitmap */
unsigned intorder;
dma_addr_t  base;
 
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index c9c6acdf..cc42bc2 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1066,6 +1066,8 @@ fs_initcall(dma_debug_do_init);
 
 /* IOMMU */
 
+static int extend_iommu_mapping(struct dma_iommu_mapping *mapping);
+
 static inline dma_addr_t __alloc_iova(struct dma_iommu_mapping *mapping,
  size_t size)
 {
@@ -1073,6 +1075,8 @@ static inline dma_addr_t __alloc_iova(struct 
dma_iommu_mapping *mapping,
unsigned int align = 0;
unsigned int count, start;
unsigned long flags;
+   dma_addr_t iova;
+   int i;
 
if (order  CONFIG_ARM_DMA_IOMMU_ALIGNMENT)
order = CONFIG_ARM_DMA_IOMMU_ALIGNMENT;
@@ -1084,30 +1088,78 @@ static inline dma_addr_t __alloc_iova(struct 
dma_iommu_mapping *mapping,
align = (1  (order - mapping-order)) - 1;
 
spin_lock_irqsave(mapping-lock, flags);
-   start = bitmap_find_next_zero_area(mapping-bitmap, mapping-bits, 0,
-  count, align);
-   if (start  mapping-bits) {
-   spin_unlock_irqrestore(mapping-lock, flags);
-   return DMA_ERROR_CODE;
+   for (i = 0; i  mapping-nr_bitmaps; i++) {
+   start = bitmap_find_next_zero_area(mapping-bitmaps[i],
+   mapping-bits, 0, count, align);
+
+   if (start  mapping-bits)
+   continue;
+
+   bitmap_set(mapping-bitmaps[i], start, count);
+   break;
}
 
-   bitmap_set(mapping-bitmap, start, count);
+   /*
+* No unused range found. Try to extend the existing mapping
+* and perform a second attempt to reserve an IO virtual
+* address range of size bytes.
+*/
+   if (i == mapping-nr_bitmaps) {
+   if (extend_iommu_mapping(mapping)) {
+   spin_unlock_irqrestore(mapping-lock, flags);
+   return DMA_ERROR_CODE;
+   }
+
+   start = bitmap_find_next_zero_area(mapping-bitmaps[i],
+   mapping-bits, 0, count, align);
+
+   if (start  mapping-bits) {
+   spin_unlock_irqrestore(mapping-lock, flags);
+   return DMA_ERROR_CODE;
+   }
+
+   bitmap_set(mapping-bitmaps[i], start, count);
+   }
spin_unlock_irqrestore(mapping-lock, flags);
 
-   return mapping-base + (start  (mapping-order + PAGE_SHIFT));
+   iova = mapping-base + (mapping-size * i);
+   iova += start  (mapping-order + PAGE_SHIFT);
+
+   return iova;
 }
 
 static inline void __free_iova(struct dma_iommu_mapping *mapping,
   dma_addr_t addr, size_t size)
 {
-   unsigned int start = (addr - mapping-base

Re: [PATCH 0/5] OMAP IOMMU fixes and IOMMU architecture questions

2014-04-04 Thread Marek Szyprowski

Hello,

I'm sorry for a delay, I've got back from my holidays and I'm still busy 
trying

to get thought all the emails.

On 2014-03-17 23:44, Laurent Pinchart wrote:

Hi Suman and Sakari,

On Monday 17 March 2014 14:58:24 Suman Anna wrote:
 On 03/16/2014 04:54 PM, Sakari Ailus wrote:
  On Fri, Mar 14, 2014 at 12:00:16PM +0100, Laurent Pinchart wrote:
  Hi Suman,
 
  (CC'ing Joerg Roedel and Marek Szyprowski for the core IOMMU discussion)
 
  On Thursday 13 March 2014 21:33:37 Suman Anna wrote:
  On 03/07/2014 06:46 PM, Laurent Pinchart wrote:
  Hello,
 
  This patch set fixes miscellaneous issues with the OMAP IOMMU driver,
  found when trying to port the OMAP3 ISP away from omap-iovmm to the ARM
  DMA API. The biggest issue is fixed by patch 5/5, while the other
  patches fix smaller problems that I've noticed when reading the code,
  without experiencing them at runtime.
 
  I'd like to take this as an opportunity to discuss OMAP IOMMU
  integration with the ARM DMA mapping implementation. The idea is to
  hide the IOMMU completely behind the DMA mapping API, making it
  completely transparent to drivers.
 
  Thanks for starting the discussion.
 
  A drivers will only need to allocate memory with dma_alloc_*, and
  behind the scene the ARM DMA mapping implementation will find out that
  the device is behind an IOMMU and will map the buffers through the
  IOMMU, returning an I/O VA address to the driver. No direct call to the
  OMAP IOMMU driver or to the IOMMU core should be necessary anymore.
 
  To use the IOMMU the ARM DMA implementation requires a VA mapping to be
  created with a call to arm_iommu_create_mapping() and to then be
  attached to the device with arm_iommu_attach_device(). This is
  currently not performed by the OMAP IOMMU driver, I have thus added
  that code to the OMAP3 ISP driver for now. I believe this to still be
  an improvement compared to the current situation, as it allows getting
  rid of custom memory allocation code in the OMAP3 ISP driver and custom
  I/O VA space management in omap-iovmm. However, that code should
  ideally be removed from the driver. The question is, where should it be
  moved to ?
 
  One possible solution would be to add the code to the OMAP IOMMU
  driver. However, this would require all OMAP IOMMU users to be
  converted to the ARM DMA API. I assume there would be issues that I
  don't foresee though.
 
  Yeah, I think this will pose some problems for the other main user of
  IOMMUs - the remoteproc devices (DSP, Dual-Cortex M3/M4 processors in
  OMAP4 and beyond). A remoteproc device also needs to map memory at
  specific addresses for its code and data sections, and not rely on a
  I/O VA address being given to it. The firmware sections are already
  linked at specific addresses, and so remoteproc needs to allocate
  memory, load the firmware and map into appropriate device addresses. We
  are doing this currently usage a combination of CMA memory to get
  contiguous memory (there are some restrictions for certain sections) and
  iommu_map/unmap API to program the MMU with these pages. This usage is
  different from what is expected from exchanging buffers, which can be
  allocated from a predefined mapping range. Even that one is tricky if we
  need to support different cache properties/attributes as the cache
  configuration is in general local to these processors.
 
  Right, we indeed need two levels of API, one for drivers such as
  remoteproc that need direct control of the IOMMU, and one for drivers
  that only need to map buffers without any additional requirement. In the
  second case the drivers should ideally use the DMA mapping API not even
  be aware that an IOMMU is present. This would require moving the ARM
  mapping allocation out of the client driver.

 Actually, I think there is one another use case, even with remoteprocs which
 is to runtime map buffers. This is different from the firmware management.
 The memory for buffers could have been allocated from other subsystems, but
 remoteproc would need just to manage the VA space and map.

Right, although you might not always have to manage the VA space in that case.
Anyway, if your driver needs to manage the VA space for the firmware, it
should be able to manage the VA space for the buffers using the same IOMMU
API.


I've already seen some use cases which require to give a client device 
limited

access to DMA mapping IOMMU related structures. If we agree on API, I see no
problems to add such calls to dma-mapping. However in the most common case I
would like to hide the presence of IOMMU from the client device at all.


  The IOMMU core or the IOMMU driver will need to know whether the driver
  expects to control the IOMMU directly or to have it managed
  transparently. As this is a software configuration I don't think the
  information belongs to DT. The question is, how should this information
  be conveyed?

 Can this be done through iommu_domain_set_attr? But that means

Re: [PATCH] arm: dma-mapping: Fix mapping size value

2014-04-22 Thread Marek Szyprowski

Hello,

On 2014-04-21 08:47, Ritesh Harjani wrote:

68efd7d2fb(arm: dma-mapping: remove order parameter from
arm_iommu_create_mapping()) is causing kernel panic
because it wrongly sets the value of mapping-size:

Unable to handle kernel NULL pointer dereference at virtual
address 00a0
pgd = e7a84000
[00a0] *pgd=
...
PC is at bitmap_clear+0x48/0xd0
LR is at __iommu_remove_mapping+0x130/0x164

Fix it by correcting mapping-size value.

Signed-off-by: Ritesh Harjani ritesh.harj...@gmail.com
Acked-by: Laurent Pinchart laurent.pinch...@ideasonboard.com


Thanks for spotting this issue! I'm really sorry for introducing it. I 
will push it to the fixes branch asap.



---
  arch/arm/mm/dma-mapping.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index f62aa06..6b00be1 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1963,8 +1963,8 @@ arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t 
base, size_t size)
mapping-nr_bitmaps = 1;
mapping-extensions = extensions;
mapping-base = base;
-   mapping-size = bitmap_size  PAGE_SHIFT;
mapping-bits = BITS_PER_BYTE * bitmap_size;
+   mapping-size = mapping-bits  PAGE_SHIFT;
  
  	spin_lock_init(mapping-lock);


Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH] arm: dma-mapping: Fix mapping size value

2014-04-23 Thread Marek Szyprowski

Hello,

On 2014-04-22 10:53, Will Deacon wrote:

On Mon, Apr 21, 2014 at 07:47:27AM +0100, Ritesh Harjani wrote:
 68efd7d2fb(arm: dma-mapping: remove order parameter from
 arm_iommu_create_mapping()) is causing kernel panic
 because it wrongly sets the value of mapping-size:

 Unable to handle kernel NULL pointer dereference at virtual
 address 00a0
 pgd = e7a84000
 [00a0] *pgd=
 ...
 PC is at bitmap_clear+0x48/0xd0
 LR is at __iommu_remove_mapping+0x130/0x164

 Fix it by correcting mapping-size value.

 Signed-off-by: Ritesh Harjani ritesh.harj...@gmail.com
 Acked-by: Laurent Pinchart laurent.pinch...@ideasonboard.com
 ---
  arch/arm/mm/dma-mapping.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

 diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
 index f62aa06..6b00be1 100644
 --- a/arch/arm/mm/dma-mapping.c
 +++ b/arch/arm/mm/dma-mapping.c
 @@ -1963,8 +1963,8 @@ arm_iommu_create_mapping(struct bus_type *bus, 
dma_addr_t base, size_t size)
mapping-nr_bitmaps = 1;
mapping-extensions = extensions;
mapping-base = base;
 -  mapping-size = bitmap_size  PAGE_SHIFT;
mapping-bits = BITS_PER_BYTE * bitmap_size;
 +  mapping-size = mapping-bits  PAGE_SHIFT;

Ok, but given that mapping-size is derived from mapping-bits, do we really
need both of these fields in struct dma_iommu_mapping?


You are right. I didn't notice this while I was refactoring the code. 
Ritesh,
could you update your patch and simply replace all references of 
mapping-size

with (mapping-bits  PAGE_SHIFT), probably with some temporary variable to
make the code easier to understand? I've didn't apply your patch yet.

Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH] arm: dma-mapping: Fix mapping size value

2014-04-23 Thread Marek Szyprowski

Hello,

On 2014-04-23 12:04, Ritesh Harjani wrote:

Hi Marek/Will

On Wed, Apr 23, 2014 at 3:00 PM, Laurent Pinchart
laurent.pinch...@ideasonboard.com wrote:
 Hi Marek,

 On Wednesday 23 April 2014 10:53:24 Marek Szyprowski wrote:
 On 2014-04-22 10:53, Will Deacon wrote:
  On Mon, Apr 21, 2014 at 07:47:27AM +0100, Ritesh Harjani wrote:
   68efd7d2fb(arm: dma-mapping: remove order parameter from
   arm_iommu_create_mapping()) is causing kernel panic
   because it wrongly sets the value of mapping-size:
  
   Unable to handle kernel NULL pointer dereference at virtual
   address 00a0
   pgd = e7a84000
   [00a0] *pgd=
   ...
   PC is at bitmap_clear+0x48/0xd0
   LR is at __iommu_remove_mapping+0x130/0x164
  
   Fix it by correcting mapping-size value.
  
   Signed-off-by: Ritesh Harjani ritesh.harj...@gmail.com
   Acked-by: Laurent Pinchart laurent.pinch...@ideasonboard.com
   ---
  
arch/arm/mm/dma-mapping.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
  
   diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
   index f62aa06..6b00be1 100644
   --- a/arch/arm/mm/dma-mapping.c
   +++ b/arch/arm/mm/dma-mapping.c
   @@ -1963,8 +1963,8 @@ arm_iommu_create_mapping(struct bus_type *bus,
   dma_addr_t base, size_t size) 
 mapping-nr_bitmaps = 1;
 mapping-extensions = extensions;
 mapping-base = base;
  
   - mapping-size = bitmap_size  PAGE_SHIFT;
  
 mapping-bits = BITS_PER_BYTE * bitmap_size;
  
   + mapping-size = mapping-bits  PAGE_SHIFT;
 
  Ok, but given that mapping-size is derived from mapping-bits, do we
  really need both of these fields in struct dma_iommu_mapping?

 You are right. I didn't notice this while I was refactoring the code.
 Ritesh, could you update your patch and simply replace all references of
 mapping-size with (mapping-bits  PAGE_SHIFT), probably with some
 temporary variable to make the code easier to understand? I've didn't apply
 your patch yet.

 As this patch fixes a v3.15 regression, shouldn't it be applied as-is and
 ASAP, with the cleanup that removes mapping-size coming in a later, less
 urgent patch ?

I agree with Laurent. Anyway this cleanup can be taken care when we will be
doing refactoring of common code to lib/iommu-helper.c.

Anyways, if you still insist I can prepare and submit the patch. Let me know
again on this.


Ok, I've merged the patch as is and I will send pull request soon.
Please include the above discussed cleanup while refactoring common code 
to lib.


Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v2] arm: dma-iommu: Clean up redundant variable

2014-05-20 Thread Marek Szyprowski

Hello,

On 2014-05-20 06:32, ritesh.harj...@gmail.com wrote:

From: Ritesh Harjani ritesh.harj...@gmail.com

mapping-size can be derived from mapping-bits  PAGE_SHIFT
which makes mapping-size as redundant.

Clean this up.

Signed-off-by: Ritesh Harjani ritesh.harj...@gmail.com
Reported-by: Will Deacon will.dea...@arm.com


Thanks for this cleanup. I will add it to my tree.


---
  arch/arm/include/asm/dma-iommu.h |  1 -
  arch/arm/mm/dma-mapping.c| 11 ++-
  2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h
index eec0a12..8e3fcb9 100644
--- a/arch/arm/include/asm/dma-iommu.h
+++ b/arch/arm/include/asm/dma-iommu.h
@@ -18,7 +18,6 @@ struct dma_iommu_mapping {
unsigned intextensions;
size_t  bitmap_size;/* size of a single bitmap */
size_t  bits;   /* per bitmap */
-   unsigned intsize;   /* per bitmap */
dma_addr_t  base;
  
  	spinlock_t		lock;

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 6b00be1..3d43c41 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1074,6 +1074,7 @@ static inline dma_addr_t __alloc_iova(struct 
dma_iommu_mapping *mapping,
unsigned int order = get_order(size);
unsigned int align = 0;
unsigned int count, start;
+   size_t mapping_size = mapping-bits  PAGE_SHIFT;
unsigned long flags;
dma_addr_t iova;
int i;
@@ -1119,7 +1120,7 @@ static inline dma_addr_t __alloc_iova(struct 
dma_iommu_mapping *mapping,
}
spin_unlock_irqrestore(mapping-lock, flags);
  
-	iova = mapping-base + (mapping-size * i);

+   iova = mapping-base + (mapping_size * i);
iova += start  PAGE_SHIFT;
  
  	return iova;

@@ -1129,6 +1130,7 @@ static inline void __free_iova(struct dma_iommu_mapping 
*mapping,
   dma_addr_t addr, size_t size)
  {
unsigned int start, count;
+   size_t mapping_size = mapping-bits  PAGE_SHIFT;
unsigned long flags;
dma_addr_t bitmap_base;
u32 bitmap_index;
@@ -1136,14 +1138,14 @@ static inline void __free_iova(struct dma_iommu_mapping 
*mapping,
if (!size)
return;
  
-	bitmap_index = (u32) (addr - mapping-base) / (u32) mapping-size;

+   bitmap_index = (u32) (addr - mapping-base) / (u32) mapping_size;
BUG_ON(addr  mapping-base || bitmap_index  mapping-extensions);
  
-	bitmap_base = mapping-base + mapping-size * bitmap_index;

+   bitmap_base = mapping-base + mapping_size * bitmap_index;
  
  	start = (addr - bitmap_base) 	PAGE_SHIFT;
  
-	if (addr + size  bitmap_base + mapping-size) {

+   if (addr + size  bitmap_base + mapping_size) {
/*
 * The address range to be freed reaches into the iova
 * range of the next bitmap. This should not happen as
@@ -1964,7 +1966,6 @@ arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t 
base, size_t size)
mapping-extensions = extensions;
mapping-base = base;
mapping-bits = BITS_PER_BYTE * bitmap_size;
-   mapping-size = mapping-bits  PAGE_SHIFT;
  
  	spin_lock_init(mapping-lock);
  


Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 07/29] ARM: dma-mapping: arm_iommu_attach_device: automatically set max_seg_size

2014-08-05 Thread Marek Szyprowski
If device has no max_seg_size set, we assume that there is no limit and
force it to DMA_BIT_MASK(32) to always use contiguous mappings in DMA
address space.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 arch/arm/mm/dma-mapping.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 7a996aa..8161102 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -2051,6 +2051,22 @@ int arm_iommu_attach_device(struct device *dev,
 {
int err;
 
+   /*
+* if device has no max_seg_size set, we assume that there is no limit
+* and force it to DMA_BIT_MASK(32) to always use contiguous mappings
+* in DMA address space
+*/
+   if (!dev-dma_parms) {
+   dev-dma_parms = kzalloc(sizeof(*dev-dma_parms), GFP_KERNEL);
+   if (!dev-dma_parms)
+   return -ENOMEM;
+   }
+   if (!dev-dma_parms-max_segment_size) {
+   err = dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
+   if (err)
+   return err;
+   }
+
err = iommu_attach_device(mapping-domain, dev);
if (err)
return err;
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem

2014-08-05 Thread Marek Szyprowski
/host/pci-mvebu.c   |   2 +-
 drivers/pci/host/pci-rcar-gen2.c   |   2 +-
 drivers/pci/host/pci-tegra.c   |   2 +-
 drivers/pci/host/pcie-rcar.c   |   2 +-
 drivers/soc/tegra/pmc.c|   2 +-
 include/dt-bindings/clock/exynos4.h|  10 +-
 include/linux/device.h |  12 +-
 include/linux/iommu.h  |   1 +
 include/linux/pm.h |   2 +
 include/linux/pm_domain.h  |  19 +
 33 files changed, 1016 insertions(+), 356 deletions(-)


Best regards
Marek Szyprowski
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 08/29] ARM: dma-mapping: add helpers for managing default per-device dma mappings

2014-08-05 Thread Marek Szyprowski
This patch adds 2 helpers: arm_iommu_create_default_mapping and
arm_iommu_release_default_mapping for managing default iommu-based
dma-mapping address space, created for exlusive use only by the given
device. Those helpers are convenient for setting up iommu-based
dma-mapping for most typical devices in the system.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 arch/arm/include/asm/dma-iommu.h |  5 +
 arch/arm/mm/dma-mapping.c| 31 +++
 2 files changed, 36 insertions(+)

diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h
index 8e3fcb9..ae3dac0 100644
--- a/arch/arm/include/asm/dma-iommu.h
+++ b/arch/arm/include/asm/dma-iommu.h
@@ -33,5 +33,10 @@ int arm_iommu_attach_device(struct device *dev,
struct dma_iommu_mapping *mapping);
 void arm_iommu_detach_device(struct device *dev);
 
+int arm_iommu_create_default_mapping(struct device *dev, dma_addr_t base,
+size_t size);
+
+void arm_iommu_release_default_mapping(struct device *dev);
+
 #endif /* __KERNEL__ */
 #endif
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 8161102..233a8cf 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -2106,4 +2106,35 @@ void arm_iommu_detach_device(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(arm_iommu_detach_device);
 
+int arm_iommu_create_default_mapping(struct device *dev, dma_addr_t base,
+size_t size)
+{
+   struct dma_iommu_mapping *mapping;
+   int ret;
+
+   mapping = arm_iommu_create_mapping(dev-bus, base, size);
+   if (IS_ERR(mapping))
+   return PTR_ERR(mapping);
+
+   ret = arm_iommu_attach_device(dev, mapping);
+   if (ret) {
+   arm_iommu_release_mapping(mapping);
+   return ret;
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(arm_iommu_create_default_mapping);
+
+void arm_iommu_release_default_mapping(struct device *dev)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   if (!mapping)
+   return;
+
+   arm_iommu_detach_device(dev);
+   arm_iommu_release_mapping(mapping);
+}
+EXPORT_SYMBOL_GPL(arm_iommu_release_default_mapping);
+
 #endif
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 02/29] ARM: Exynos: bind power domains earlier, on device creation

2014-08-05 Thread Marek Szyprowski
This patches change initialization time of power domain driver from client
device driver bind to device creation. This lets other core drivers to
register power domain notifiers before client driver is bound.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 arch/arm/mach-exynos/pm_domains.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-exynos/pm_domains.c 
b/arch/arm/mach-exynos/pm_domains.c
index fd76e1b..1d368a2 100644
--- a/arch/arm/mach-exynos/pm_domains.c
+++ b/arch/arm/mach-exynos/pm_domains.c
@@ -159,13 +159,13 @@ static int exynos_pm_notifier_call(struct notifier_block 
*nb,
struct device *dev = data;
 
switch (event) {
-   case BUS_NOTIFY_BIND_DRIVER:
+   case BUS_NOTIFY_ADD_DEVICE:
if (dev-of_node)
exynos_read_domain_from_dt(dev);
 
break;
 
-   case BUS_NOTIFY_UNBOUND_DRIVER:
+   case BUS_NOTIFY_DEL_DEVICE:
exynos_remove_device_from_domain(dev);
 
break;
@@ -177,6 +177,13 @@ static struct notifier_block platform_nb = {
.notifier_call = exynos_pm_notifier_call,
 };
 
+static int exynos_pm_domain_add(struct device *dev, void *priv)
+{
+   if (dev-of_node)
+   exynos_read_domain_from_dt(dev);
+   return 0;
+}
+
 static __init int exynos4_pm_init_power_domain(void)
 {
struct platform_device *pdev;
@@ -236,6 +243,7 @@ no_clk:
}
 
bus_register_notifier(platform_bus_type, platform_nb);
+   bus_for_each_dev(platform_bus_type, NULL, NULL, exynos_pm_domain_add);
 
return 0;
 }
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 11/29] DRM: exynos: add DRIVER_HAS_OWN_IOMMU_MANAGER flag to all sub-drivers

2014-08-05 Thread Marek Szyprowski
Exynos DRM drivers do their own management of IO address space of all
controlled devices, so set DRIVER_HAS_OWN_IOMMU_MANAGER flag to instruct
IOMMU subsystem not to create any defaults for them.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/gpu/drm/exynos/exynos_drm_fimc.c| 1 +
 drivers/gpu/drm/exynos/exynos_drm_fimd.c| 1 +
 drivers/gpu/drm/exynos/exynos_drm_g2d.c | 1 +
 drivers/gpu/drm/exynos/exynos_drm_gsc.c | 1 +
 drivers/gpu/drm/exynos/exynos_drm_rotator.c | 1 +
 drivers/gpu/drm/exynos/exynos_mixer.c   | 1 +
 6 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c 
b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index 831dde9..fe84215 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -1896,6 +1896,7 @@ struct platform_driver fimc_driver = {
.name   = exynos-drm-fimc,
.owner  = THIS_MODULE,
.pm = fimc_pm_ops,
+   .flags  = DRIVER_HAS_OWN_IOMMU_MANAGER,
},
 };
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c 
b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 33161ad..41904df 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -1031,5 +1031,6 @@ struct platform_driver fimd_driver = {
.name   = exynos4-fb,
.owner  = THIS_MODULE,
.of_match_table = fimd_driver_dt_match,
+   .flags  = DRIVER_HAS_OWN_IOMMU_MANAGER,
},
 };
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c 
b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 8001587..dddeae3 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -1555,5 +1555,6 @@ struct platform_driver g2d_driver = {
.owner  = THIS_MODULE,
.pm = g2d_pm_ops,
.of_match_table = exynos_g2d_match,
+   .flags  = DRIVER_HAS_OWN_IOMMU_MANAGER,
},
 };
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c 
b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index 9e3ff16..76e8b1e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -1797,6 +1797,7 @@ struct platform_driver gsc_driver = {
.name   = exynos-drm-gsc,
.owner  = THIS_MODULE,
.pm = gsc_pm_ops,
+   .flags  = DRIVER_HAS_OWN_IOMMU_MANAGER,
},
 };
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c 
b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
index f01fbb6..2da91c4 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
@@ -852,5 +852,6 @@ struct platform_driver rotator_driver = {
.owner  = THIS_MODULE,
.pm = rotator_pm_ops,
.of_match_table = exynos_rotator_match,
+   .flags  = DRIVER_HAS_OWN_IOMMU_MANAGER,
},
 };
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c 
b/drivers/gpu/drm/exynos/exynos_mixer.c
index 7529946..79b1309a 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -1320,6 +1320,7 @@ struct platform_driver mixer_driver = {
.name = exynos-mixer,
.owner = THIS_MODULE,
.of_match_table = mixer_match_types,
+   .flags  = DRIVER_HAS_OWN_IOMMU_MANAGER,
},
.probe = mixer_probe,
.remove = mixer_remove,
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 09/29] ARM: dma-mapping: provide stubs if no ARM_DMA_USE_IOMMU has been selected

2014-08-05 Thread Marek Szyprowski
This patch provides stubs returing errors for all iommu related arm
dma-mapping functions, which are used when CONFIG_ARM_DMA_USE_IOMMU is
not set. This let drivers to use common code for iommu and non-iommu
cases without additional ifdefs.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 arch/arm/include/asm/dma-iommu.h | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h
index ae3dac0..1e57569 100644
--- a/arch/arm/include/asm/dma-iommu.h
+++ b/arch/arm/include/asm/dma-iommu.h
@@ -9,6 +9,8 @@
 #include linux/kmemcheck.h
 #include linux/kref.h
 
+#ifdef CONFIG_ARM_DMA_USE_IOMMU
+
 struct dma_iommu_mapping {
/* iommu specific data */
struct iommu_domain *domain;
@@ -38,5 +40,34 @@ int arm_iommu_create_default_mapping(struct device *dev, 
dma_addr_t base,
 
 void arm_iommu_release_default_mapping(struct device *dev);
 
+#else
+
+static inline struct dma_iommu_mapping *
+arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size)
+{
+   return ERR_PTR(-ENOSYS);
+}
+
+static inline void
+arm_iommu_release_mapping(struct dma_iommu_mapping *mapping) { }
+
+static inline int arm_iommu_attach_device(struct device *dev,
+   struct dma_iommu_mapping *mapping)
+{
+   return -ENOSYS;
+}
+
+static inline void arm_iommu_detach_device(struct device *dev) { }
+
+static inline int arm_iommu_create_default_mapping(struct device *dev,
+   dma_addr_t base, size_t size)
+{
+   return -ENOSYS;
+}
+
+static inline void arm_iommu_release_default_mapping(struct device *dev) { }
+
+#endif
+
 #endif /* __KERNEL__ */
 #endif
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 18/29] iommu: exynos: remove unused functions

2014-08-05 Thread Marek Szyprowski
This patch removes two unneeded functions, which are not a part of
generic IOMMU API and were never used by any other driver.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 31 ---
 1 file changed, 31 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 8927923..ec3c882 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -491,13 +491,6 @@ static int __exynos_sysmmu_enable(struct device *dev, 
phys_addr_t pgtable,
return ret;
 }
 
-int exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable)
-{
-   BUG_ON(!memblock_is_memory(pgtable));
-
-   return __exynos_sysmmu_enable(dev, pgtable, NULL);
-}
-
 static bool exynos_sysmmu_disable(struct device *dev)
 {
unsigned long flags;
@@ -589,30 +582,6 @@ static void sysmmu_tlb_invalidate_entry(struct device 
*dev, sysmmu_iova_t iova,
spin_unlock_irqrestore(data-lock, flags);
 }
 
-void exynos_sysmmu_tlb_invalidate(struct device *dev)
-{
-   struct exynos_iommu_owner *owner = dev-archdata.iommu;
-   unsigned long flags;
-   struct sysmmu_drvdata *data;
-
-   data = dev_get_drvdata(owner-sysmmu);
-
-   spin_lock_irqsave(data-lock, flags);
-   if (is_sysmmu_active(data)) {
-   if (!IS_ERR(data-clk_master))
-   clk_enable(data-clk_master);
-   if (sysmmu_block(data-sfrbase)) {
-   __sysmmu_tlb_invalidate(data-sfrbase);
-   sysmmu_unblock(data-sfrbase);
-   }
-   if (!IS_ERR(data-clk_master))
-   clk_disable(data-clk_master);
-   } else {
-   dev_dbg(dev, disabled. Skipping TLB invalidation\n);
-   }
-   spin_unlock_irqrestore(data-lock, flags);
-}
-
 static int __init exynos_sysmmu_probe(struct platform_device *pdev)
 {
int irq, ret;
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 14/29] devicetree: Update Exynos SYSMMU device tree bindings

2014-08-05 Thread Marek Szyprowski
This patch describes how generic iommu bindings are implemented by
Exynos SYSMMU driver.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 .../devicetree/bindings/iommu/samsung,sysmmu.txt   | 93 +++---
 1 file changed, 84 insertions(+), 9 deletions(-)

diff --git a/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt 
b/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt
index 6fa4c73..999ba6d 100644
--- a/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt
+++ b/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt
@@ -23,16 +23,33 @@ MMUs.
   for window 1, 2 and 3.
 * M2M Scalers and G2D in Exynos5420 has one System MMU on the read channel and
   the other System MMU on the write channel.
-The drivers must consider how to handle those System MMUs. One of the idea is
-to implement child devices or sub-devices which are the client devices of the
-System MMU.
 
-Note:
-The current DT binding for the Exynos System MMU is incomplete.
-The following properties can be removed or changed, if found incompatible with
-the Generic IOMMU Binding support for attaching devices to the IOMMU.
+The drivers must consider how to handle those System MMUs. When device
+have more than one SYSMMU controller it is neccessary to add
+iommu-names property, which specifies which SYSMMU controller operates
+on which bus or memory channel.
 
-Required properties:
+It is up to the master device driver to decide how such case will be
+handled. It is possible to create separate IO address spaces for each
+SYSMMU or to bind them together to one common IO address space. It is
+also possible to bind more than one device to one IO address space. All
+this has to be handled by master device driver in its initialization
+procedure or flags and no changes to device tree nodes are needed.
+
+In Linux kernel, the general idea is that presence of the SYSMMU
+controllers is transparent to master drivers if they use standard DMA
+API. When driver wants to use IO separate address spaces for each bus or
+memory channel (each SYSMMU) or to bind more than one device to one IO
+address space, it has to specify this to SYSMMU driver by
+DRIVER_HAS_OWN_IOMMU_MANAGER flag. To get access to each SYSMMU bound to
+the given device, additional child devices with special names (matching
+parent:bus scheme) have to be registered. Once then, all standard
+IOMMU operations can be performed on such child devices, what will
+result in respective operations done on IO address space managed by
+SYSMMU of the given name. Other operating systems might implement those
+features differently.
+
+Required properties for SYSMMU controller node:
 - compatible: Should be samsung,exynos-sysmmu
 - reg: A tuple of base address and size of System MMU registers.
 - interrupt-parent: The phandle of the interrupt controller of System MMU
@@ -45,11 +62,27 @@ Required properties:
   Exynos4 SoCs, there needs no master clock.
   Exynos5 SoCs, some System MMUs must have master clocks.
 - clocks: Required if the System MMU is needed to gate its clock.
+- #iommu-cells: Specify number of cells describing IO address space parameters,
+   can be: 0 (zero), meaning all 32bit address space is available,
+   or 2, if address space is limited, first cell then stores
+   base IO address, second cell contains IO window size in bytes.
 - samsung,power-domain: Required if the System MMU is needed to gate its power.
  Please refer to the following document:
  Documentation/devicetree/bindings/arm/exynos/power_domain.txt
 
-Examples:
+Required properties for master device:
+- iommus: one or more phandles to the SYSMMU controller node, with optionally
+ specified IO address space (see #iommu-cells property above)
+- iommu-names: if more than one SYSMMU controller is specified, this property
+  must contain names for each of them. Those names are defined by
+  the bindings for a particular master device.
+
+For more information, please refer to generic iommu bindings defined in
+iommu.txt file.
+
+Example 1:
+GScaller device with one SYSMMU controller
+
gsc_0: gsc@13e0 {
compatible = samsung,exynos5-gsc;
reg = 0x13e0 0x1000;
@@ -57,6 +90,7 @@ Examples:
samsung,power-domain = pd_gsc;
clocks = clock CLK_GSCL0;
clock-names = gscl;
+   iommus = sysmmu_gsc0;
};
 
sysmmu_gsc0: sysmmu@13E8 {
@@ -67,4 +101,45 @@ Examples:
clock-names = sysmmu, master;
clocks = clock CLK_SMMU_GSCL0, clock CLK_GSCL0;
samsung,power-domain = pd_gsc;
+   #iommu-cells = 0;
+   };
+
+Example 2:
+MFC Codec with two SYSMMU controllers (on left and right bus), with address
+space limited to 256MiB each, left bus starts IO address space at 0x2000,
+while right bus at 0x3000

[PATCH 05/29] drivers: convert suppress_bind_attrs parameter into flags

2014-08-05 Thread Marek Szyprowski
This patch extends struct device_driver with a flags member and converts
existing suppress_bind_attrs bool field to a flag. This way new flags
can be easily added in the future without changing the structure itself.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 arch/arm/mach-integrator/impd1.c | 2 +-
 drivers/base/bus.c   | 4 ++--
 drivers/base/platform.c  | 2 +-
 drivers/pci/host/pci-mvebu.c | 2 +-
 drivers/pci/host/pci-rcar-gen2.c | 2 +-
 drivers/pci/host/pci-tegra.c | 2 +-
 drivers/pci/host/pcie-rcar.c | 2 +-
 drivers/soc/tegra/pmc.c  | 2 +-
 include/linux/device.h   | 6 --
 9 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
index 3ce8807..a7e7330 100644
--- a/arch/arm/mach-integrator/impd1.c
+++ b/arch/arm/mach-integrator/impd1.c
@@ -406,7 +406,7 @@ static struct lm_driver impd1_driver = {
 * As we're dropping the probe() function, suppress driver
 * binding from sysfs.
 */
-   .suppress_bind_attrs = true,
+   .flags = DRIVER_SUPPRESS_BIND_ATTRS,
},
.probe  = impd1_probe,
.remove = impd1_remove,
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 83e910a..f223f26 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -707,7 +707,7 @@ int bus_add_driver(struct device_driver *drv)
__func__, drv-name);
}
 
-   if (!drv-suppress_bind_attrs) {
+   if (!(drv-flags  DRIVER_SUPPRESS_BIND_ATTRS)) {
error = add_bind_files(drv);
if (error) {
/* Ditto */
@@ -740,7 +740,7 @@ void bus_remove_driver(struct device_driver *drv)
if (!drv-bus)
return;
 
-   if (!drv-suppress_bind_attrs)
+   if (!(drv-flags  DRIVER_SUPPRESS_BIND_ATTRS))
remove_bind_files(drv);
driver_remove_groups(drv, drv-bus-drv_groups);
driver_remove_file(drv, driver_attr_uevent);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 68a8b77..c696058 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -608,7 +608,7 @@ int __init_or_module platform_driver_probe(struct 
platform_driver *drv,
drv-prevent_deferred_probe = true;
 
/* make sure driver won't have bind/unbind attributes */
-   drv-driver.suppress_bind_attrs = true;
+   drv-driver.flags = DRIVER_SUPPRESS_BIND_ATTRS;
 
/* temporary section violation during probe() */
drv-probe = probe;
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index a8c6f1a..6815c50 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -1086,7 +1086,7 @@ static struct platform_driver mvebu_pcie_driver = {
.name = mvebu-pcie,
.of_match_table = mvebu_pcie_of_match_table,
/* driver unloading/unbinding currently not supported */
-   .suppress_bind_attrs = true,
+   .flags = DRIVER_SUPPRESS_BIND_ATTRS,
},
.probe = mvebu_pcie_probe,
 };
diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c
index 3ef854f..6f1b890 100644
--- a/drivers/pci/host/pci-rcar-gen2.c
+++ b/drivers/pci/host/pci-rcar-gen2.c
@@ -413,7 +413,7 @@ static struct platform_driver rcar_pci_driver = {
.driver = {
.name = pci-rcar-gen2,
.owner = THIS_MODULE,
-   .suppress_bind_attrs = true,
+   .flags = DRIVER_SUPPRESS_BIND_ATTRS,
.of_match_table = rcar_pci_of_match,
},
.probe = rcar_pci_probe,
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 0fb0fdb..2e1698d 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -1927,7 +1927,7 @@ static struct platform_driver tegra_pcie_driver = {
.name = tegra-pcie,
.owner = THIS_MODULE,
.of_match_table = tegra_pcie_of_match,
-   .suppress_bind_attrs = true,
+   .flags = DRIVER_SUPPRESS_BIND_ATTRS,
},
.probe = tegra_pcie_probe,
 };
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 4884ee5..9a1936e 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -981,7 +981,7 @@ static struct platform_driver rcar_pcie_driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
.of_match_table = rcar_pcie_of_match,
-   .suppress_bind_attrs = true,
+   .flags = DRIVER_SUPPRESS_BIND_ATTRS,
},
.probe = rcar_pcie_probe,
 };
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index a2c0ceb..77c3eb3 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -892,7 +892,7 @@ static const struct

[PATCH 20/29] iommu: exynos: refactor function parameters to simplify code

2014-08-05 Thread Marek Szyprowski
This patch simplifies the code by:
- refactoring function parameters from struct device pointer to direct pointer
  to struct sysmmu drvdata
- moving list_head enteries from struct exynos_iommu_owner directly to struct
  sysmmu_drvdata

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 93 ++--
 1 file changed, 46 insertions(+), 47 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index ed8c518..018a615 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -187,8 +187,6 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
 
 /* attached to dev.archdata.iommu of the master device */
 struct exynos_iommu_owner {
-   struct list_head client; /* entry of exynos_iommu_domain.clients */
-   struct device *dev;
struct device *sysmmu;
 };
 
@@ -209,6 +207,7 @@ struct sysmmu_drvdata {
int activations;
spinlock_t lock;
struct iommu_domain *domain;
+   struct list_head domain_node;
phys_addr_t pgtable;
int version;
 };
@@ -509,12 +508,10 @@ static void __sysmmu_tlb_invalidate_flpdcache(struct 
sysmmu_drvdata *data,
__raw_writel(iova | 0x1, data-sfrbase + REG_MMU_FLUSH_ENTRY);
 }
 
-static void sysmmu_tlb_invalidate_flpdcache(struct device *dev,
+static void sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
sysmmu_iova_t iova)
 {
unsigned long flags;
-   struct exynos_iommu_owner *owner = dev-archdata.iommu;
-   struct sysmmu_drvdata *data = dev_get_drvdata(owner-sysmmu);
 
if (!IS_ERR(data-clk_master))
clk_enable(data-clk_master);
@@ -528,14 +525,10 @@ static void sysmmu_tlb_invalidate_flpdcache(struct device 
*dev,
clk_disable(data-clk_master);
 }
 
-static void sysmmu_tlb_invalidate_entry(struct device *dev, sysmmu_iova_t iova,
-   size_t size)
+static void sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data,
+   sysmmu_iova_t iova, size_t size)
 {
-   struct exynos_iommu_owner *owner = dev-archdata.iommu;
unsigned long flags;
-   struct sysmmu_drvdata *data;
-
-   data = dev_get_drvdata(owner-sysmmu);
 
spin_lock_irqsave(data-lock, flags);
if (is_sysmmu_active(data)) {
@@ -565,8 +558,8 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, 
sysmmu_iova_t iova,
if (!IS_ERR(data-clk_master))
clk_disable(data-clk_master);
} else {
-   dev_dbg(dev, disabled. Skipping TLB invalidation @ %#x\n,
-   iova);
+   dev_dbg(data-master,
+   disabled. Skipping TLB invalidation @ %#x\n, iova);
}
spin_unlock_irqrestore(data-lock, flags);
 }
@@ -705,7 +698,7 @@ err_pgtable:
 static void exynos_iommu_domain_destroy(struct iommu_domain *domain)
 {
struct exynos_iommu_domain *priv = domain-priv;
-   struct exynos_iommu_owner *owner;
+   struct sysmmu_drvdata *data;
unsigned long flags;
int i;
 
@@ -713,14 +706,12 @@ static void exynos_iommu_domain_destroy(struct 
iommu_domain *domain)
 
spin_lock_irqsave(priv-lock, flags);
 
-   list_for_each_entry(owner, priv-clients, client) {
-   while (!exynos_sysmmu_disable(owner-dev))
-   ; /* until System MMU is actually disabled */
+   list_for_each_entry(data, priv-clients, domain_node) {
+   if (__sysmmu_disable(data))
+   data-master = NULL;
+   list_del_init(data-domain_node);
}
 
-   while (!list_empty(priv-clients))
-   list_del_init(priv-clients.next);
-
spin_unlock_irqrestore(priv-lock, flags);
 
for (i = 0; i  NUM_LV1ENTRIES; i++)
@@ -739,20 +730,26 @@ static int exynos_iommu_attach_device(struct iommu_domain 
*domain,
 {
struct exynos_iommu_owner *owner = dev-archdata.iommu;
struct exynos_iommu_domain *priv = domain-priv;
+   struct sysmmu_drvdata *data;
phys_addr_t pagetable = virt_to_phys(priv-pgtable);
unsigned long flags;
-   int ret;
+   int ret = -ENODEV;
 
-   spin_lock_irqsave(priv-lock, flags);
+   if (!has_sysmmu(dev))
+   return -ENODEV;
 
-   ret = __exynos_sysmmu_enable(dev, pagetable, domain);
-   if (ret == 0) {
-   list_add_tail(owner-client, priv-clients);
-   owner-domain = domain;
+   data = dev_get_drvdata(owner-sysmmu);
+   if (data) {
+   ret = __sysmmu_enable(data, pagetable, domain);
+   if (ret = 0) {
+   data-master = dev;
+
+   spin_lock_irqsave(priv-lock, flags);
+   list_add_tail(data-domain_node, priv-clients

[PATCH 13/29] temporary: media: s5p-mfc: remove DT hacks initialization custom memory init code

2014-08-05 Thread Marek Szyprowski
This patch removes custom initialization of reserved memory regions from
s5p-mfc driver. Driver will use main device pointer for all memory allocations.

This patch is temporary, do not merge it yet.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c | 73 +---
 1 file changed, 2 insertions(+), 71 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index d35b041..77b99ae 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -996,55 +996,8 @@ static const struct v4l2_file_operations s5p_mfc_fops = {
.mmap = s5p_mfc_mmap,
 };
 
-static int match_child(struct device *dev, void *data)
-{
-   if (!dev_name(dev))
-   return 0;
-   return !strcmp(dev_name(dev), (char *)data);
-}
-
 static void *mfc_get_drv_data(struct platform_device *pdev);
 
-static int s5p_mfc_alloc_memdevs(struct s5p_mfc_dev *dev)
-{
-   unsigned int mem_info[2] = { };
-
-   dev-mem_dev_l = devm_kzalloc(dev-plat_dev-dev,
-   sizeof(struct device), GFP_KERNEL);
-   if (!dev-mem_dev_l) {
-   mfc_err(Not enough memory\n);
-   return -ENOMEM;
-   }
-   device_initialize(dev-mem_dev_l);
-   of_property_read_u32_array(dev-plat_dev-dev.of_node,
-   samsung,mfc-l, mem_info, 2);
-   if (dma_declare_coherent_memory(dev-mem_dev_l, mem_info[0],
-   mem_info[0], mem_info[1],
-   DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0) {
-   mfc_err(Failed to declare coherent memory for\n
-   MFC device\n);
-   return -ENOMEM;
-   }
-
-   dev-mem_dev_r = devm_kzalloc(dev-plat_dev-dev,
-   sizeof(struct device), GFP_KERNEL);
-   if (!dev-mem_dev_r) {
-   mfc_err(Not enough memory\n);
-   return -ENOMEM;
-   }
-   device_initialize(dev-mem_dev_r);
-   of_property_read_u32_array(dev-plat_dev-dev.of_node,
-   samsung,mfc-r, mem_info, 2);
-   if (dma_declare_coherent_memory(dev-mem_dev_r, mem_info[0],
-   mem_info[0], mem_info[1],
-   DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0) {
-   pr_err(Failed to declare coherent memory for\n
-   MFC device\n);
-   return -ENOMEM;
-   }
-   return 0;
-}
-
 /* MFC probe function */
 static int s5p_mfc_probe(struct platform_device *pdev)
 {
@@ -1096,26 +1049,8 @@ static int s5p_mfc_probe(struct platform_device *pdev)
goto err_res;
}
 
-   if (pdev-dev.of_node) {
-   ret = s5p_mfc_alloc_memdevs(dev);
-   if (ret  0)
-   goto err_res;
-   } else {
-   dev-mem_dev_l = device_find_child(dev-plat_dev-dev,
-   s5p-mfc-l, match_child);
-   if (!dev-mem_dev_l) {
-   mfc_err(Mem child (L) device get failed\n);
-   ret = -ENODEV;
-   goto err_res;
-   }
-   dev-mem_dev_r = device_find_child(dev-plat_dev-dev,
-   s5p-mfc-r, match_child);
-   if (!dev-mem_dev_r) {
-   mfc_err(Mem child (R) device get failed\n);
-   ret = -ENODEV;
-   goto err_res;
-   }
-   }
+   dev-mem_dev_l = dev-plat_dev-dev;
+   dev-mem_dev_r = dev-plat_dev-dev;
 
dev-alloc_ctx[0] = vb2_dma_contig_init_ctx(dev-mem_dev_l);
if (IS_ERR(dev-alloc_ctx[0])) {
@@ -1246,10 +1181,6 @@ static int s5p_mfc_remove(struct platform_device *pdev)
s5p_mfc_release_firmware(dev);
vb2_dma_contig_cleanup_ctx(dev-alloc_ctx[0]);
vb2_dma_contig_cleanup_ctx(dev-alloc_ctx[1]);
-   if (pdev-dev.of_node) {
-   put_device(dev-mem_dev_l);
-   put_device(dev-mem_dev_r);
-   }
 
s5p_mfc_final_pm(dev);
return 0;
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 12/29] DRM: Exynos: fix window clear code

2014-08-05 Thread Marek Szyprowski
To correctly disable hardware window during driver init, both enable bits
(WINCONx_ENWIN in WINCON and SHADOWCON_CHx_ENABLE in SHADOWCON) must be
cleared, otherwise hardware fails to re-enable such window later.

While touching this function, also temporarily disable ctx-suspended flag
to let fimd_wait_for_vblank function really to do its job.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/gpu/drm/exynos/exynos_drm_fimd.c | 25 ++---
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c 
b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 41904df..7a363d2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -165,27 +165,38 @@ static void fimd_wait_for_vblank(struct 
exynos_drm_manager *mgr)
DRM_DEBUG_KMS(vblank wait timed out.\n);
 }
 
-
 static void fimd_clear_channel(struct exynos_drm_manager *mgr)
 {
struct fimd_context *ctx = mgr-ctx;
-   int win, ch_enabled = 0;
+   int state, win, ch_enabled = 0;
 
DRM_DEBUG_KMS(%s\n, __FILE__);
 
/* Check if any channel is enabled. */
for (win = 0; win  WINDOWS_NR; win++) {
-   u32 val = readl(ctx-regs + SHADOWCON);
-   if (val  SHADOWCON_CHx_ENABLE(win)) {
-   val = ~SHADOWCON_CHx_ENABLE(win);
-   writel(val, ctx-regs + SHADOWCON);
+   u32 val = readl(ctx-regs + WINCON(win));
+   if (val  WINCONx_ENWIN) {
+   /* wincon */
+   val = ~WINCONx_ENWIN;
+   writel(val, ctx-regs + WINCON(win));
+
+   /* unprotect windows */
+   if (ctx-driver_data-has_shadowcon) {
+   val = readl(ctx-regs + SHADOWCON);
+   val = ~SHADOWCON_CHx_ENABLE(win);
+   writel(val, ctx-regs + SHADOWCON);
+   }
ch_enabled = 1;
}
}
 
/* Wait for vsync, as disable channel takes effect at next vsync */
-   if (ch_enabled)
+   if (ch_enabled) {
+   state = ctx-suspended;
+   ctx-suspended = 0;
fimd_wait_for_vblank(mgr);
+   ctx-suspended = state;
+   }
 }
 
 static int fimd_mgr_initialize(struct exynos_drm_manager *mgr,
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 04/29] drivers: base: add notifier for failed driver bind

2014-08-05 Thread Marek Szyprowski
This patch adds support for getting a notify for failed device driver
bind, so all the items done in BUS_NOTIFY_BIND_DRIVER event can be
cleaned if the driver fails to bind.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/base/dd.c  | 10 +++---
 include/linux/device.h |  4 +++-
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index e4ffbcf..541a41f 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -237,10 +237,14 @@ static int driver_sysfs_add(struct device *dev)
return ret;
 }
 
-static void driver_sysfs_remove(struct device *dev)
+static void driver_sysfs_remove(struct device *dev, int failed)
 {
struct device_driver *drv = dev-driver;
 
+   if (failed  dev-bus)
+   blocking_notifier_call_chain(dev-bus-p-bus_notifier,
+BUS_NOTIFY_DRVBIND_FAILED, dev);
+
if (drv) {
sysfs_remove_link(drv-p-kobj, kobject_name(dev-kobj));
sysfs_remove_link(dev-kobj, driver);
@@ -316,7 +320,7 @@ static int really_probe(struct device *dev, struct 
device_driver *drv)
 
 probe_failed:
devres_release_all(dev);
-   driver_sysfs_remove(dev);
+   driver_sysfs_remove(dev, true);
dev-driver = NULL;
dev_set_drvdata(dev, NULL);
 
@@ -509,7 +513,7 @@ static void __device_release_driver(struct device *dev)
if (drv) {
pm_runtime_get_sync(dev);
 
-   driver_sysfs_remove(dev);
+   driver_sysfs_remove(dev, false);
 
if (dev-bus)
blocking_notifier_call_chain(dev-bus-p-bus_notifier,
diff --git a/include/linux/device.h b/include/linux/device.h
index b387710..92daded 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -176,7 +176,7 @@ extern int bus_register_notifier(struct bus_type *bus,
 extern int bus_unregister_notifier(struct bus_type *bus,
   struct notifier_block *nb);
 
-/* All 4 notifers below get called with the target struct device *
+/* All 7 notifers below get called with the target struct device *
  * as an argument. Note that those functions are likely to be called
  * with the device lock held in the core, so be careful.
  */
@@ -189,6 +189,8 @@ extern int bus_unregister_notifier(struct bus_type *bus,
  unbound */
 #define BUS_NOTIFY_UNBOUND_DRIVER  0x0006 /* driver is unbound
  from the device */
+#define BUS_NOTIFY_DRVBIND_FAILED  0x0007 /* driver failed to bind
+ to device */
 
 extern struct kset *bus_get_kset(struct bus_type *bus);
 extern struct klist *bus_get_device_klist(struct bus_type *bus);
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 10/29] drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag

2014-08-05 Thread Marek Szyprowski
This patch adds a new flags for device drivers. This flag instructs
kernel that the device driver does it own management of IOMMU assisted
IO address space translations, so no default dma-mapping structures
should be initialized.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 include/linux/device.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/device.h b/include/linux/device.h
index 5f4ff02..2e62371 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -253,6 +253,8 @@ struct device_driver {
 
 /* disables bind/unbind via sysfs */
 #define DRIVER_SUPPRESS_BIND_ATTRS (1  0)
+/* driver uses own methods to manage IO address space */
+#define DRIVER_HAS_OWN_IOMMU_MANAGER   (1  1)
 
 extern int __must_check driver_register(struct device_driver *drv);
 extern void driver_unregister(struct device_driver *drv);
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 03/29] clk: exynos: add missing smmu_g2d clock and update comments

2014-08-05 Thread Marek Szyprowski
This patch adds missing smmu_g2d clock implementation and updates
comment about Exynos4 clocks from 278-282 range. Those clocks are
available on all Exynos4 SoC series, so the misleading comment has been
removed.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/clk/samsung/clk-exynos4.c   |  1 +
 include/dt-bindings/clock/exynos4.h | 10 +-
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c 
b/drivers/clk/samsung/clk-exynos4.c
index ac163d7..12a7cc3 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -1183,6 +1183,7 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] 
__initdata = {
GATE(CLK_SPI1_ISP, spi1_isp, aclk200, E4X12_GATE_ISP1, 13,
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
GATE(CLK_G2D, g2d, aclk200, GATE_IP_DMC, 23, 0, 0),
+   GATE(CLK_SMMU_G2D, smmu_g2d, aclk200, GATE_IP_DMC, 24, 0, 0),
GATE(CLK_TMU_APBIF, tmu_apbif, aclk100, E4X12_GATE_IP_PERIR, 17, 0,
0),
 };
diff --git a/include/dt-bindings/clock/exynos4.h 
b/include/dt-bindings/clock/exynos4.h
index 459bd2b..fb981635 100644
--- a/include/dt-bindings/clock/exynos4.h
+++ b/include/dt-bindings/clock/exynos4.h
@@ -115,11 +115,11 @@
 #define CLK_SMMU_MFCR  275
 #define CLK_G3D276
 #define CLK_G2D277
-#define CLK_ROTATOR278 /* Exynos4210 only */
-#define CLK_MDMA   279 /* Exynos4210 only */
-#define CLK_SMMU_G2D   280 /* Exynos4210 only */
-#define CLK_SMMU_ROTATOR   281 /* Exynos4210 only */
-#define CLK_SMMU_MDMA  282 /* Exynos4210 only */
+#define CLK_ROTATOR278
+#define CLK_MDMA   279
+#define CLK_SMMU_G2D   280
+#define CLK_SMMU_ROTATOR   281
+#define CLK_SMMU_MDMA  282
 #define CLK_FIMD0  283
 #define CLK_MIE0   284
 #define CLK_MDNIE0 285 /* Exynos4412 only */
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 17/29] iommu: exynos: don't read version register on every tlb operation

2014-08-05 Thread Marek Szyprowski
This patch removes reading of REG_MMU_VERSION register on every tlb
operation and caches SYSMMU version in driver's internal data.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 13 +
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 64b3bc8..8927923 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -213,6 +213,7 @@ struct sysmmu_drvdata {
spinlock_t lock;
struct iommu_domain *domain;
phys_addr_t pgtable;
+   int version;
 };
 
 static bool set_sysmmu_active(struct sysmmu_drvdata *data)
@@ -239,11 +240,6 @@ static void sysmmu_unblock(void __iomem *sfrbase)
__raw_writel(CTRL_ENABLE, sfrbase + REG_MMU_CTRL);
 }
 
-static unsigned int __raw_sysmmu_version(struct sysmmu_drvdata *data)
-{
-   return MMU_RAW_VER(__raw_readl(data-sfrbase + REG_MMU_VERSION));
-}
-
 static bool sysmmu_block(void __iomem *sfrbase)
 {
int i = 120;
@@ -403,7 +399,7 @@ static void __sysmmu_init_config(struct sysmmu_drvdata 
*data)
unsigned int cfg = CFG_LRU | CFG_QOS(15);
unsigned int ver;
 
-   ver = __raw_sysmmu_version(data);
+   ver = MMU_RAW_VER(__raw_readl(data-sfrbase + REG_MMU_VERSION));
if (MMU_MAJ_VER(ver) == 3) {
if (MMU_MIN_VER(ver) = 2) {
cfg |= CFG_FLPDCACHE;
@@ -417,6 +413,7 @@ static void __sysmmu_init_config(struct sysmmu_drvdata 
*data)
}
 
__raw_writel(cfg, data-sfrbase + REG_MMU_CFG);
+   data-version = ver;
 }
 
 static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data)
@@ -526,7 +523,7 @@ static bool exynos_sysmmu_disable(struct device *dev)
 static void __sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
  sysmmu_iova_t iova)
 {
-   if (__raw_sysmmu_version(data) == MAKE_MMU_VER(3, 3))
+   if (data-version == MAKE_MMU_VER(3, 3))
__raw_writel(iova | 0x1, data-sfrbase + REG_MMU_FLUSH_ENTRY);
 }
 
@@ -575,7 +572,7 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, 
sysmmu_iova_t iova,
 * 1MB page can be cached in one of all sets.
 * 64KB page can be one of 16 consecutive sets.
 */
-   if (MMU_MAJ_VER(__raw_sysmmu_version(data)) == 2)
+   if (MMU_MAJ_VER(data-version) == 2)
num_inv = min_t(unsigned int, size / PAGE_SIZE, 64);
 
if (sysmmu_block(data-sfrbase)) {
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 25/29] iommu: exynos: add support for runtime_pm

2014-08-05 Thread Marek Szyprowski
This patch enables support for runtime pm for SYSMMU controllers. State
of each controller is saved before master's device power domain is
turned off and restored after it has been turned on.

exynos_iommu_attach_device() function might be called anytime, even when
power domain for master's device has been turned off, so to let SYSMMU
controllers to access its registers, a call to pm_runtime_get_sync() has
to be done, which turns on the power domain, which SYSMMU belongs to.
Later, once SYSMMU has been enabled, a call to pm_runtime_put() lets
runtime pm to turn off the power domain if there are no other devices
enabled. This way, the SYSMMU drivers get a genpd pm event and save its
state with sysmmu_save_state() function.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 54 +++-
 1 file changed, 53 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 336b2f8..5cd91b11 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -28,6 +28,7 @@
 #include linux/list.h
 #include linux/memblock.h
 #include linux/export.h
+#include linux/pm_domain.h
 
 #include asm/cacheflush.h
 #include asm/dma-iommu.h
@@ -208,6 +209,7 @@ struct sysmmu_drvdata {
struct clk *clk;
struct clk *clk_master;
int activations;
+   int suspended;
spinlock_t lock;
struct iommu_domain *domain;
struct list_head domain_node;
@@ -217,6 +219,7 @@ struct sysmmu_drvdata {
const char *name;
dma_addr_t base;
size_t size;
+   struct notifier_block pm_notifier;
 };
 
 static bool set_sysmmu_active(struct sysmmu_drvdata *data)
@@ -235,7 +238,7 @@ static bool set_sysmmu_inactive(struct sysmmu_drvdata *data)
 
 static bool is_sysmmu_active(struct sysmmu_drvdata *data)
 {
-   return data-activations  0;
+   return (!data-suspended  data-activations  0);
 }
 
 static void sysmmu_unblock(void __iomem *sfrbase)
@@ -528,6 +531,51 @@ static void sysmmu_tlb_invalidate_entry(struct 
sysmmu_drvdata *data,
spin_unlock_irqrestore(data-lock, flags);
 }
 
+static void sysmmu_restore_state(struct sysmmu_drvdata *data)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(data-lock, flags);
+   if (data-activations  0) {
+   data-suspended = false;
+   __sysmmu_enable_nocount(data);
+   dev_dbg(data-sysmmu, restored state\n);
+   }
+   spin_unlock_irqrestore(data-lock, flags);
+}
+
+static void sysmmu_save_state(struct sysmmu_drvdata *data)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(data-lock, flags);
+   if (data-activations  0) {
+   __sysmmu_disable_nocount(data);
+   data-suspended = true;
+   dev_dbg(data-sysmmu, saved state\n);
+   }
+   spin_unlock_irqrestore(data-lock, flags);
+}
+
+static int sysmmu_runtime_genpd_event(struct notifier_block *this,
+   unsigned long event, void *ptr)
+{
+   struct sysmmu_drvdata *data;
+
+   data = container_of(this, struct sysmmu_drvdata, pm_notifier);
+
+   switch (event) {
+   case PM_GENPD_POST_POWER_ON:
+   sysmmu_restore_state(data);
+   break;
+   case PM_GENPD_POWER_OFF_PREPARE:
+   sysmmu_save_state(data);
+   break;
+   }
+
+   return NOTIFY_DONE;
+}
+
 static int __init exynos_sysmmu_probe(struct platform_device *pdev)
 {
int irq, ret;
@@ -580,6 +628,7 @@ static int __init exynos_sysmmu_probe(struct 
platform_device *pdev)
}
 
data-sysmmu = dev;
+   data-pm_notifier.notifier_call = sysmmu_runtime_genpd_event;
 
/* default io address space parameters */
data-base = SZ_1G;
@@ -708,6 +757,7 @@ static int exynos_iommu_attach_device(struct iommu_domain 
*domain,
return -ENODEV;
 
list_for_each_entry(data, owner-clients, owner_node) {
+   pm_runtime_get_sync(data-sysmmu);
ret = __sysmmu_enable(data, pagetable, domain);
if (ret = 0) {
data-master = dev;
@@ -716,6 +766,7 @@ static int exynos_iommu_attach_device(struct iommu_domain 
*domain,
list_add_tail(data-domain_node, priv-clients);
spin_unlock_irqrestore(priv-lock, flags);
}
+   pm_runtime_put(data-sysmmu);
}
 
if (ret  0) {
@@ -1156,6 +1207,7 @@ static int __init_master_sysmmu(struct device *dev)
}
 
list_add_tail(data-owner_node, owner-clients);
+   pm_genpd_register_notifier(dev, data-pm_notifier);
 
i++;
}
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 16/29] iommu: exynos: make driver multiarch friendly

2014-08-05 Thread Marek Szyprowski
Initialize all structures and register to iommu subsystem only on Exynos
compatible platforms.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index d037e87..64b3bc8 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -20,6 +20,7 @@
 #include linux/clk.h
 #include linux/err.h
 #include linux/mm.h
+#include linux/of.h
 #include linux/iommu.h
 #include linux/errno.h
 #include linux/list.h
@@ -1187,6 +1188,11 @@ static int __init exynos_iommu_init(void)
 {
int ret;
 
+   if (!of_machine_is_compatible(samsung,exynos3) 
+   !of_machine_is_compatible(samsung,exynos4) 
+   !of_machine_is_compatible(samsung,exynos5))
+   return -ENODEV;
+
lv2table_kmem_cache = kmem_cache_create(exynos-iommu-lv2table,
LV2TABLE_SIZE, LV2TABLE_SIZE, 0, NULL);
if (!lv2table_kmem_cache) {
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 19/29] iommu: exynos: remove useless spinlock

2014-08-05 Thread Marek Szyprowski
This patch removes useless spinlocks and other unused members from
struct exynos_iommu_owner. There is no point is protecting this
structure by spinlock because content of this structure doesn't change
and other structures have their own spinlocks.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 11 ---
 1 file changed, 11 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index ec3c882..ed8c518 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -190,9 +190,6 @@ struct exynos_iommu_owner {
struct list_head client; /* entry of exynos_iommu_domain.clients */
struct device *dev;
struct device *sysmmu;
-   struct iommu_domain *domain;
-   void *vmm_data; /* IO virtual memory manager's data */
-   spinlock_t lock;/* Lock to preserve consistency of System MMU */
 };
 
 struct exynos_iommu_domain {
@@ -478,16 +475,12 @@ static int __exynos_sysmmu_enable(struct device *dev, 
phys_addr_t pgtable,
 
BUG_ON(!has_sysmmu(dev));
 
-   spin_lock_irqsave(owner-lock, flags);
-
data = dev_get_drvdata(owner-sysmmu);
 
ret = __sysmmu_enable(data, pgtable, domain);
if (ret = 0)
data-master = dev;
 
-   spin_unlock_irqrestore(owner-lock, flags);
-
return ret;
 }
 
@@ -500,16 +493,12 @@ static bool exynos_sysmmu_disable(struct device *dev)
 
BUG_ON(!has_sysmmu(dev));
 
-   spin_lock_irqsave(owner-lock, flags);
-
data = dev_get_drvdata(owner-sysmmu);
 
disabled = __sysmmu_disable(data);
if (disabled)
data-master = NULL;
 
-   spin_unlock_irqrestore(owner-lock, flags);
-
return disabled;
 }
 
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 15/29] ARM: DTS: Exynos4: add System MMU nodes

2014-08-05 Thread Marek Szyprowski
This patch adds System MMU nodes that are specific to Exynos4210/4x12 series.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 arch/arm/boot/dts/exynos4.dtsi| 118 ++
 arch/arm/boot/dts/exynos4210.dtsi |  23 
 arch/arm/boot/dts/exynos4x12.dtsi |  82 ++
 3 files changed, 223 insertions(+)

diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index 3385b17..a76b4e5 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -174,6 +174,7 @@
clock-names = fimc, sclk_fimc;
samsung,power-domain = pd_cam;
samsung,sysreg = sys_reg;
+   iommus = sysmmu_fimc0;
status = disabled;
};
 
@@ -185,6 +186,7 @@
clock-names = fimc, sclk_fimc;
samsung,power-domain = pd_cam;
samsung,sysreg = sys_reg;
+   iommus = sysmmu_fimc1;
status = disabled;
};
 
@@ -196,6 +198,7 @@
clock-names = fimc, sclk_fimc;
samsung,power-domain = pd_cam;
samsung,sysreg = sys_reg;
+   iommus = sysmmu_fimc2;
status = disabled;
};
 
@@ -207,6 +210,7 @@
clock-names = fimc, sclk_fimc;
samsung,power-domain = pd_cam;
samsung,sysreg = sys_reg;
+   iommus = sysmmu_fimc3;
status = disabled;
};
 
@@ -395,6 +399,9 @@
clocks = clock CLK_MFC;
clock-names = mfc;
status = disabled;
+   iommus = sysmmu_mfc_l 0x2000 0x1000,
+sysmmu_mfc_r 0x3000 0x1000;
+   iommu-names = left, right;
};
 
serial_0: serial@1380 {
@@ -642,6 +649,117 @@
clocks = clock CLK_SCLK_FIMD0, clock CLK_FIMD0;
clock-names = sclk_fimd, fimd;
samsung,power-domain = pd_lcd0;
+   iommus = sysmmu_fimd0;
status = disabled;
};
+
+   sysmmu_mfc_l: sysmmu@1362 {
+   compatible = samsung,exynos-sysmmu;
+   reg = 0x1362 0x1000;
+   interrupt-parent = combiner;
+   interrupts = 5 5;
+   clock-names = sysmmu, master;
+   clocks = clock CLK_SMMU_MFCL, clock CLK_MFC;
+   samsung,power-domain = pd_mfc;
+   #iommu-cells = 2;
+   };
+
+   sysmmu_mfc_r: sysmmu@1363 {
+   compatible = samsung,exynos-sysmmu;
+   reg = 0x1363 0x1000;
+   interrupt-parent = combiner;
+   interrupts = 5 6;
+   clock-names = sysmmu, master;
+   clocks = clock CLK_SMMU_MFCR, clock CLK_MFC;
+   samsung,power-domain = pd_mfc;
+   #iommu-cells = 2;
+   };
+
+   sysmmu_tv: sysmmu@12E2 {
+   compatible = samsung,exynos-sysmmu;
+   reg = 0x12E2 0x1000;
+   interrupt-parent = combiner;
+   interrupts = 5 4;
+   clock-names = sysmmu, master;
+   clocks = clock CLK_SMMU_TV, clock CLK_MIXER;
+   samsung,power-domain = pd_tv;
+   #iommu-cells = 0;
+   };
+
+   sysmmu_fimc0: sysmmu@11A2 {
+   compatible = samsung,exynos-sysmmu;
+   reg = 0x11A2 0x1000;
+   interrupt-parent = combiner;
+   interrupts = 4 2;
+   clock-names = sysmmu, master;
+   clocks = clock CLK_SMMU_FIMC0, clock CLK_FIMC0;
+   samsung,power-domain = pd_cam;
+   #iommu-cells = 0;
+   };
+
+   sysmmu_fimc1: sysmmu@11A3 {
+   compatible = samsung,exynos-sysmmu;
+   reg = 0x11A3 0x1000;
+   interrupt-parent = combiner;
+   interrupts = 4 3;
+   clock-names = sysmmu, master;
+   clocks = clock CLK_SMMU_FIMC1, clock CLK_FIMC1;
+   samsung,power-domain = pd_cam;
+   #iommu-cells = 0;
+   };
+
+   sysmmu_fimc2: sysmmu@11A4 {
+   compatible = samsung,exynos-sysmmu;
+   reg = 0x11A4 0x1000;
+   interrupt-parent = combiner;
+   interrupts = 4 4;
+   clock-names = sysmmu, master;
+   clocks = clock CLK_SMMU_FIMC2, clock CLK_FIMC2;
+   samsung,power-domain = pd_cam;
+   #iommu-cells = 0;
+   };
+
+   sysmmu_fimc3: sysmmu@11A5 {
+   compatible = samsung,exynos-sysmmu;
+   reg = 0x11A5 0x1000;
+   interrupt-parent = combiner

[PATCH 23/29] iommu: exynos: init iommu controllers from device tree

2014-08-05 Thread Marek Szyprowski
This patch adds code to initialize and assign SYSMMU controllers to
their master devices defined in device tree.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 152 +--
 1 file changed, 145 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 46e0edc..845f547 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -21,6 +21,7 @@
 #include linux/err.h
 #include linux/mm.h
 #include linux/of.h
+#include linux/of_platform.h
 #include linux/iommu.h
 #include linux/errno.h
 #include linux/list.h
@@ -211,6 +212,9 @@ struct sysmmu_drvdata {
struct list_head owner_node;
phys_addr_t pgtable;
int version;
+   const char *name;
+   dma_addr_t base;
+   size_t size;
 };
 
 static bool set_sysmmu_active(struct sysmmu_drvdata *data)
@@ -574,6 +578,11 @@ static int __init exynos_sysmmu_probe(struct 
platform_device *pdev)
}
 
data-sysmmu = dev;
+
+   /* default io address space parameters */
+   data-base = SZ_1G;
+   data-size = SZ_2G;
+
spin_lock_init(data-lock);
 
platform_set_drvdata(pdev, data);
@@ -1055,30 +1064,159 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct 
iommu_domain *domain,
return phys;
 }
 
+static void __free_owner_struct(struct exynos_iommu_owner *owner,
+   struct device *dev)
+{
+   while (!list_empty(owner-clients))
+   list_del_init(owner-clients.next);
+
+   kfree(owner);
+   dev-archdata.iommu = NULL;
+}
+
+static int __init_master_sysmmu(struct device *dev)
+{
+   struct of_phandle_args sysmmu_spec;
+   struct exynos_iommu_owner *owner;
+   int i = 0;
+   int ret;
+
+   owner = kzalloc(sizeof(*owner), GFP_KERNEL);
+   if (!owner)
+   return -ENOMEM;
+   INIT_LIST_HEAD(owner-clients);
+
+   while (!of_parse_phandle_with_args(dev-of_node, iommus,
+  #iommu-cells, i,
+  sysmmu_spec)) {
+   struct platform_device *sysmmu;
+   struct sysmmu_drvdata *data;
+
+   sysmmu = of_find_device_by_node(sysmmu_spec.np);
+   if (!sysmmu) {
+   dev_err(dev, sysmmu node not found\n);
+   ret = -ENODEV;
+   goto err;
+   }
+   data = platform_get_drvdata(sysmmu);
+   if (!data) {
+   ret = -ENODEV;
+   goto err;
+   }
+
+   of_property_read_string_index(dev-of_node, iommu-names, i,
+ data-name);
+
+   if (sysmmu_spec.args_count == 2) {
+   data-base = sysmmu_spec.args[0];
+   data-size = sysmmu_spec.args[1];
+   } else if (sysmmu_spec.args_count != 0) {
+   dev_err(dev, incorrect iommu property specified\n);
+   ret = -EINVAL;
+   goto err;
+   }
+
+   list_add_tail(data-owner_node, owner-clients);
+
+   i++;
+   }
+
+   if (i == 0) {
+   ret = -ENODEV;
+   goto err;
+   }
+
+   dev-archdata.iommu = owner;
+   dev_dbg(dev, registered %d sysmmu controllers\n, i);
+
+   return 0;
+err:
+   __free_owner_struct(owner, dev);
+   return ret;
+}
+
+static int __init_subdevice_sysmmu(struct device *dev)
+{
+   struct device *parent = dev-parent;
+   struct exynos_iommu_owner *owner;
+   struct sysmmu_drvdata *data;
+   char *name;
+
+   name = strrchr(dev_name(dev), ':');
+   if (!name)
+   return -ENODEV;
+   name++;
+
+   owner = parent-archdata.iommu;
+   if (!owner)
+   return -ENODEV;
+
+   list_for_each_entry(data, owner-clients, owner_node)
+   if (strcmp(name, data-name) == 0)
+   break;
+   if (!data)
+   return -ENODEV;
+
+   owner = kzalloc(sizeof(*owner), GFP_KERNEL);
+   if (!owner)
+   return -ENOMEM;
+   INIT_LIST_HEAD(owner-clients);
+
+   /* move sysmmu from parent to child device */
+   list_del(data-owner_node);
+   list_add_tail(data-owner_node, owner-clients);
+
+   dev-archdata.iommu = owner;
+   dev_dbg(dev-parent,
+   registered sysmmu controller for %s subdevice\n, data-name);
+
+   return 0;
+}
+
 static int exynos_iommu_add_device(struct device *dev)
 {
struct iommu_group *group;
int ret;
 
-   group = iommu_group_get(dev);
+   BUG_ON(dev-archdata.iommu != NULL);
 
-   if (!group) {
-   group = iommu_group_alloc();
-   if (IS_ERR(group)) {
-   dev_err(dev, Failed

[PATCH 27/29] iommu: exynos: document internal structures

2014-08-05 Thread Marek Szyprowski
Add a few words of comment to all internal structures used by the driver.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 59 
 1 file changed, 38 insertions(+), 21 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 7600861..78ce618 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -189,37 +189,54 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
UNKNOWN FAULT
 };
 
-/* attached to dev.archdata.iommu of the master device */
+/*
+ * This structure is attached to dev.archdata.iommu of the master device
+ * on device add, contains a list of SYSMMU controllers defined by device tree,
+ * which are bound to given master device. It is usually referenced by 'owner'
+ * pointer.
+ */
 struct exynos_iommu_owner {
-   struct list_head clients;
+   struct list_head clients; /* list of sysmmu_drvdata.owner_node */
 };
 
+/*
+ * This structure is stored in -priv field of generic struct iommu_domain,
+ * contains list of SYSMMU controllers from all master devices, which has been
+ * attached to this domain and page tables of IO address space defined by this
+ * domain. It is usually referenced by 'domain' pointer.
+ */
 struct exynos_iommu_domain {
-   struct list_head clients; /* list of sysmmu_drvdata.node */
+   struct list_head clients; /* list of sysmmu_drvdata.domain_node */
sysmmu_pte_t *pgtable; /* lv1 page table, 16KB */
short *lv2entcnt; /* free lv2 entry counter for each section */
-   spinlock_t lock; /* lock for this structure */
+   spinlock_t lock; /* lock for modyfying list of clients */
spinlock_t pgtablelock; /* lock for modifying page table @ pgtable */
 };
 
+/*
+ * This structure hold all data of a single SYSMMU controller, this includes
+ * hw resources like registers and clocks, pointers and list nodes to connect
+ * it to all other structures, internal state and parameters read from device
+ * tree. It is usually referenced by 'data' pointer.
+ */
 struct sysmmu_drvdata {
-   struct device *sysmmu;  /* System MMU's device descriptor */
-   struct device *master;  /* Owner of system MMU */
-   void __iomem *sfrbase;
-   struct clk *clk;
-   struct clk *clk_master;
-   int activations;
-   int suspended;
-   spinlock_t lock;
-   struct iommu_domain *domain;
-   struct list_head domain_node;
-   struct list_head owner_node;
-   phys_addr_t pgtable;
-   int version;
-   const char *name;
-   dma_addr_t base;
-   size_t size;
-   struct notifier_block pm_notifier;
+   struct device *sysmmu; /* SYSMMU controller device */
+   struct device *master; /* master device (owner of given SYSMMU) */
+   void __iomem *sfrbase; /* our registers */
+   struct clk *clk; /* SYSMMU's clock */
+   struct clk *clk_master; /* master's device clock */
+   int activations; /* number of calls to sysmmu_enable */
+   int suspended; /* status of the controller (managed by runtime pm) */
+   spinlock_t lock; /* lock for modyfying enable/disable state */
+   struct iommu_domain *domain; /* domain we belong to */
+   struct list_head domain_node; /* node for domain clients list */
+   struct list_head owner_node; /* node for owner clients list */
+   phys_addr_t pgtable; /* assigned page table structure */
+   int version; /* our version */
+   const char *name; /* our name from device tree */
+   dma_addr_t base; /* base addres of IO address space define in DT */
+   size_t size; /* size of IO address space define in DT */
+   struct notifier_block pm_notifier; /* notifier for pm domain on/off */
 };
 
 static bool set_sysmmu_active(struct sysmmu_drvdata *data)
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 21/29] iommu: exynos: remove unused functions, part 2

2014-08-05 Thread Marek Szyprowski
After refactoring functions to use pointer to struct sysmmu_drvdata
directly, some functions became useless and thus never used, so remove
them completely.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 43 ---
 1 file changed, 43 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 018a615..674d1fb 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -458,49 +458,6 @@ static int __sysmmu_enable(struct sysmmu_drvdata *data,
return ret;
 }
 
-/* __exynos_sysmmu_enable: Enables System MMU
- *
- * returns -error if an error occurred and System MMU is not enabled,
- * 0 if the System MMU has been just enabled and 1 if System MMU was already
- * enabled before.
- */
-static int __exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable,
- struct iommu_domain *domain)
-{
-   int ret = 0;
-   unsigned long flags;
-   struct exynos_iommu_owner *owner = dev-archdata.iommu;
-   struct sysmmu_drvdata *data;
-
-   BUG_ON(!has_sysmmu(dev));
-
-   data = dev_get_drvdata(owner-sysmmu);
-
-   ret = __sysmmu_enable(data, pgtable, domain);
-   if (ret = 0)
-   data-master = dev;
-
-   return ret;
-}
-
-static bool exynos_sysmmu_disable(struct device *dev)
-{
-   unsigned long flags;
-   bool disabled = true;
-   struct exynos_iommu_owner *owner = dev-archdata.iommu;
-   struct sysmmu_drvdata *data;
-
-   BUG_ON(!has_sysmmu(dev));
-
-   data = dev_get_drvdata(owner-sysmmu);
-
-   disabled = __sysmmu_disable(data);
-   if (disabled)
-   data-master = NULL;
-
-   return disabled;
-}
-
 static void __sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
  sysmmu_iova_t iova)
 {
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 26/29] iommu: exynos: rename variables to reflect their purpose

2014-08-05 Thread Marek Szyprowski
This patch renames some variables to make the code easier to understand.
'domain' is replaced by 'iommu_domain' (more generic entity) and really
meaning less 'priv' by 'domain' to reflect its purpose.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 191 ++-
 1 file changed, 97 insertions(+), 94 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 5cd91b11..7600861 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -440,8 +440,8 @@ static void __sysmmu_enable_nocount(struct sysmmu_drvdata 
*data)
clk_disable(data-clk_master);
 }
 
-static int __sysmmu_enable(struct sysmmu_drvdata *data,
-   phys_addr_t pgtable, struct iommu_domain *domain)
+static int __sysmmu_enable(struct sysmmu_drvdata *data, phys_addr_t pgtable,
+  struct iommu_domain *iommu_domain)
 {
int ret = 0;
unsigned long flags;
@@ -449,7 +449,7 @@ static int __sysmmu_enable(struct sysmmu_drvdata *data,
spin_lock_irqsave(data-lock, flags);
if (set_sysmmu_active(data)) {
data-pgtable = pgtable;
-   data-domain = domain;
+   data-domain = iommu_domain;
 
__sysmmu_enable_nocount(data);
 
@@ -664,92 +664,93 @@ static inline void pgtable_flush(void *vastart, void 
*vaend)
virt_to_phys(vaend));
 }
 
-static int exynos_iommu_domain_init(struct iommu_domain *domain)
+static int exynos_iommu_domain_init(struct iommu_domain *iommu_domain)
 {
-   struct exynos_iommu_domain *priv;
+   struct exynos_iommu_domain *domain;
int i;
 
-   priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-   if (!priv)
+   domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+   if (!domain)
return -ENOMEM;
 
-   priv-pgtable = (sysmmu_pte_t *)__get_free_pages(GFP_KERNEL, 2);
-   if (!priv-pgtable)
+   domain-pgtable = (sysmmu_pte_t *)__get_free_pages(GFP_KERNEL, 2);
+   if (!domain-pgtable)
goto err_pgtable;
 
-   priv-lv2entcnt = (short *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
-   if (!priv-lv2entcnt)
+   domain-lv2entcnt = (short *)
+   __get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
+   if (!domain-lv2entcnt)
goto err_counter;
 
/* w/a of System MMU v3.3 to prevent caching 1MiB mapping */
for (i = 0; i  NUM_LV1ENTRIES; i += 8) {
-   priv-pgtable[i + 0] = ZERO_LV2LINK;
-   priv-pgtable[i + 1] = ZERO_LV2LINK;
-   priv-pgtable[i + 2] = ZERO_LV2LINK;
-   priv-pgtable[i + 3] = ZERO_LV2LINK;
-   priv-pgtable[i + 4] = ZERO_LV2LINK;
-   priv-pgtable[i + 5] = ZERO_LV2LINK;
-   priv-pgtable[i + 6] = ZERO_LV2LINK;
-   priv-pgtable[i + 7] = ZERO_LV2LINK;
+   domain-pgtable[i + 0] = ZERO_LV2LINK;
+   domain-pgtable[i + 1] = ZERO_LV2LINK;
+   domain-pgtable[i + 2] = ZERO_LV2LINK;
+   domain-pgtable[i + 3] = ZERO_LV2LINK;
+   domain-pgtable[i + 4] = ZERO_LV2LINK;
+   domain-pgtable[i + 5] = ZERO_LV2LINK;
+   domain-pgtable[i + 6] = ZERO_LV2LINK;
+   domain-pgtable[i + 7] = ZERO_LV2LINK;
}
 
-   pgtable_flush(priv-pgtable, priv-pgtable + NUM_LV1ENTRIES);
+   pgtable_flush(domain-pgtable, domain-pgtable + NUM_LV1ENTRIES);
 
-   spin_lock_init(priv-lock);
-   spin_lock_init(priv-pgtablelock);
-   INIT_LIST_HEAD(priv-clients);
+   spin_lock_init(domain-lock);
+   spin_lock_init(domain-pgtablelock);
+   INIT_LIST_HEAD(domain-clients);
 
-   domain-geometry.aperture_start = 0;
-   domain-geometry.aperture_end   = ~0UL;
-   domain-geometry.force_aperture = true;
+   iommu_domain-geometry.aperture_start = 0;
+   iommu_domain-geometry.aperture_end   = ~0UL;
+   iommu_domain-geometry.force_aperture = true;
 
-   domain-priv = priv;
+   iommu_domain-priv = domain;
return 0;
 
 err_counter:
-   free_pages((unsigned long)priv-pgtable, 2);
+   free_pages((unsigned long)domain-pgtable, 2);
 err_pgtable:
-   kfree(priv);
+   kfree(domain);
return -ENOMEM;
 }
 
-static void exynos_iommu_domain_destroy(struct iommu_domain *domain)
+static void exynos_iommu_domain_destroy(struct iommu_domain *iommu_domain)
 {
-   struct exynos_iommu_domain *priv = domain-priv;
+   struct exynos_iommu_domain *domain = iommu_domain-priv;
struct sysmmu_drvdata *data;
unsigned long flags;
int i;
 
-   WARN_ON(!list_empty(priv-clients));
+   WARN_ON(!list_empty(domain-clients));
 
-   spin_lock_irqsave(priv-lock, flags);
+   spin_lock_irqsave(domain-lock, flags);
 
-   list_for_each_entry(data, priv-clients, domain_node

[PATCH 24/29] iommu: exynos: create default iommu-based dma-mapping for master devices

2014-08-05 Thread Marek Szyprowski
This patch adds code to create default per-device iommu-based
dma-mapping instance for all master devices, whose driver didn't set
DRIVER_HAS_OWN_IOMMU_MANAGER flag.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 49 +++-
 1 file changed, 48 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 845f547..336b2f8 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -12,6 +12,7 @@
 #define DEBUG
 #endif
 
+#include linux/dma-mapping.h
 #include linux/io.h
 #include linux/interrupt.h
 #include linux/platform_device.h
@@ -29,6 +30,7 @@
 #include linux/export.h
 
 #include asm/cacheflush.h
+#include asm/dma-iommu.h
 #include asm/pgtable.h
 
 typedef u32 sysmmu_iova_t;
@@ -1064,6 +1066,43 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct 
iommu_domain *domain,
return phys;
 }
 
+static int sysmmu_master_device_event(struct notifier_block *nb,
+ unsigned long val, void *p)
+{
+   struct device *dev = p;
+   struct exynos_iommu_owner *owner = dev-archdata.iommu;
+   struct sysmmu_drvdata *data;
+
+   if (!owner)
+   return 0;
+
+   data = list_first_entry(owner-clients, struct sysmmu_drvdata,
+   owner_node);
+   if (!data)
+   return 0;
+
+   switch (val) {
+
+   case IOMMU_GROUP_NOTIFY_BIND_DRIVER:
+   if (!(dev-driver-flags  DRIVER_HAS_OWN_IOMMU_MANAGER))
+   arm_iommu_create_default_mapping(dev, data-base,
+data-size);
+   break;
+
+   case IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER:
+   case IOMMU_GROUP_NOTIFY_DRVBIND_FAILED:
+   if (!(dev-driver-flags  DRIVER_HAS_OWN_IOMMU_MANAGER))
+   arm_iommu_release_default_mapping(dev);
+   break;
+   }
+
+   return 0;
+}
+
+static struct notifier_block sysmmu_master_device_notifier = {
+   .notifier_call = sysmmu_master_device_event,
+};
+
 static void __free_owner_struct(struct exynos_iommu_owner *owner,
struct device *dev)
 {
@@ -1202,6 +1241,7 @@ static int exynos_iommu_add_device(struct device *dev)
if (ret != 0)
goto err;
 
+   iommu_group_register_notifier(group, sysmmu_master_device_notifier);
iommu_group_put(group);
 
return 0;
@@ -1213,8 +1253,15 @@ err:
 static void exynos_iommu_remove_device(struct device *dev)
 {
struct exynos_iommu_owner *owner = dev-archdata.iommu;
+   struct iommu_group *group = iommu_group_get(dev);
+
+   if (group) {
+   iommu_group_unregister_notifier(group,
+   sysmmu_master_device_notifier);
+   iommu_group_remove_device(dev);
+   iommu_group_put(group);
+   }
 
-   iommu_group_remove_device(dev);
if (owner)
__free_owner_struct(owner, dev);
 }
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 28/29] iommu: exynos: remove excessive includes and sort others alphabetically

2014-08-05 Thread Marek Szyprowski
Removed following unused includes: linux/mm.h, linux/errno.h,
linux/memblock.h and linux/export.h.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 18 +++---
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 78ce618..1bbb100 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -12,23 +12,19 @@
 #define DEBUG
 #endif
 
+#include linux/clk.h
 #include linux/dma-mapping.h
+#include linux/err.h
 #include linux/io.h
+#include linux/iommu.h
 #include linux/interrupt.h
-#include linux/platform_device.h
-#include linux/slab.h
-#include linux/pm_runtime.h
-#include linux/clk.h
-#include linux/err.h
-#include linux/mm.h
+#include linux/list.h
 #include linux/of.h
 #include linux/of_platform.h
-#include linux/iommu.h
-#include linux/errno.h
-#include linux/list.h
-#include linux/memblock.h
-#include linux/export.h
+#include linux/platform_device.h
 #include linux/pm_domain.h
+#include linux/pm_runtime.h
+#include linux/slab.h
 
 #include asm/cacheflush.h
 #include asm/dma-iommu.h
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 22/29] iommu: exynos: add support for binding more than one sysmmu to master device

2014-08-05 Thread Marek Szyprowski
This patch adds support for assigning more than one SYSMMU controller to
the master device. This has been achieved simply by chaning the struct
device pointer in struct exynos_iommu_owner into the list of struct
sysmmu_drvdata of all controllers assigned to the given master device.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 674d1fb..46e0edc 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -187,7 +187,7 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
 
 /* attached to dev.archdata.iommu of the master device */
 struct exynos_iommu_owner {
-   struct device *sysmmu;
+   struct list_head clients;
 };
 
 struct exynos_iommu_domain {
@@ -208,6 +208,7 @@ struct sysmmu_drvdata {
spinlock_t lock;
struct iommu_domain *domain;
struct list_head domain_node;
+   struct list_head owner_node;
phys_addr_t pgtable;
int version;
 };
@@ -695,8 +696,7 @@ static int exynos_iommu_attach_device(struct iommu_domain 
*domain,
if (!has_sysmmu(dev))
return -ENODEV;
 
-   data = dev_get_drvdata(owner-sysmmu);
-   if (data) {
+   list_for_each_entry(data, owner-clients, owner_node) {
ret = __sysmmu_enable(data, pagetable, domain);
if (ret = 0) {
data-master = dev;
@@ -724,7 +724,7 @@ static void exynos_iommu_detach_device(struct iommu_domain 
*domain,
 {
struct exynos_iommu_domain *priv = domain-priv;
phys_addr_t pagetable = virt_to_phys(priv-pgtable);
-   struct sysmmu_drvdata *data;
+   struct sysmmu_drvdata *data, *next;
unsigned long flags;
int found = 0;
 
@@ -732,14 +732,13 @@ static void exynos_iommu_detach_device(struct 
iommu_domain *domain,
return;
 
spin_lock_irqsave(priv-lock, flags);
-   list_for_each_entry(data, priv-clients, domain_node) {
+   list_for_each_entry_safe(data, next, priv-clients, domain_node) {
if (data-master == dev) {
if (__sysmmu_disable(data)) {
data-master = NULL;
list_del_init(data-domain_node);
}
found = true;
-   break;
}
}
spin_unlock_irqrestore(priv-lock, flags);
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 29/29] temporary: media: s5p-mfc: add support for IOMMU

2014-08-05 Thread Marek Szyprowski
This patch is an example how to use more than one IOMMU controller in a
device driver for hardware blocks, which have more then one dma master
(memory interface with iommu controller).

This patch is temporary, do not merge it yet.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c | 46 ++--
 1 file changed, 44 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 77b99ae..c2e95ab 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -22,7 +22,11 @@
 #include media/v4l2-event.h
 #include linux/workqueue.h
 #include linux/of.h
+#include linux/of_platform.h
 #include media/videobuf2-core.h
+
+#include asm/dma-iommu.h
+
 #include s5p_mfc_common.h
 #include s5p_mfc_ctrl.h
 #include s5p_mfc_debug.h
@@ -996,6 +1000,39 @@ static const struct v4l2_file_operations s5p_mfc_fops = {
.mmap = s5p_mfc_mmap,
 };
 
+static struct device *s5p_mfc_alloc_memdev(struct device *dev, const char 
*name)
+{
+   struct device *child;
+   int ret;
+
+   child = devm_kzalloc(dev, sizeof(struct device), GFP_KERNEL);
+   if (!child)
+   return NULL;
+
+   device_initialize(child);
+   dev_set_name(child, %s:%s, dev_name(dev), name);
+   child-parent = dev;
+   child-bus = dev-bus;
+   child-coherent_dma_mask = dev-coherent_dma_mask;
+   child-dma_mask = dev-dma_mask;
+
+   if (device_add(child) == 0) {
+   ret = arm_iommu_create_default_mapping(child, 0x2000,
+  SZ_256M);
+   if (ret == 0)
+   return child;
+   }
+
+   put_device(child);
+   return NULL;
+}
+
+void s5p_mfc_free_memdev(struct device *dev)
+{
+   arm_iommu_release_default_mapping(dev);
+   put_device(dev);
+}
+
 static void *mfc_get_drv_data(struct platform_device *pdev);
 
 /* MFC probe function */
@@ -1049,8 +1086,8 @@ static int s5p_mfc_probe(struct platform_device *pdev)
goto err_res;
}
 
-   dev-mem_dev_l = dev-plat_dev-dev;
-   dev-mem_dev_r = dev-plat_dev-dev;
+   dev-mem_dev_l = s5p_mfc_alloc_memdev(dev-plat_dev-dev, left);
+   dev-mem_dev_r = s5p_mfc_alloc_memdev(dev-plat_dev-dev, right);
 
dev-alloc_ctx[0] = vb2_dma_contig_init_ctx(dev-mem_dev_l);
if (IS_ERR(dev-alloc_ctx[0])) {
@@ -1181,6 +1218,10 @@ static int s5p_mfc_remove(struct platform_device *pdev)
s5p_mfc_release_firmware(dev);
vb2_dma_contig_cleanup_ctx(dev-alloc_ctx[0]);
vb2_dma_contig_cleanup_ctx(dev-alloc_ctx[1]);
+   if (dev-mem_dev_l)
+   s5p_mfc_free_memdev(dev-mem_dev_l);
+   if (dev-mem_dev_r)
+   s5p_mfc_free_memdev(dev-mem_dev_r);
 
s5p_mfc_final_pm(dev);
return 0;
@@ -1436,6 +1477,7 @@ static struct platform_driver s5p_mfc_driver = {
.owner  = THIS_MODULE,
.pm = s5p_mfc_pm_ops,
.of_match_table = exynos_mfc_match,
+   .flags  = DRIVER_HAS_OWN_IOMMU_MANAGER,
},
 };
 
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem

2014-08-19 Thread Marek Szyprowski

Hello,

On 2014-08-19 01:32, Joerg Roedel wrote:

On Tue, Aug 05, 2014 at 12:47:28PM +0200, Marek Szyprowski wrote:

  .../devicetree/bindings/iommu/samsung,sysmmu.txt   |  93 ++-
  Documentation/power/notifiers.txt  |  14 +
  arch/arm/boot/dts/exynos4.dtsi | 118 
  arch/arm/boot/dts/exynos4210.dtsi  |  23 +
  arch/arm/boot/dts/exynos4x12.dtsi  |  82 +++
  arch/arm/include/asm/dma-iommu.h   |  36 ++
  arch/arm/mach-exynos/pm_domains.c  |  12 +-
  arch/arm/mach-integrator/impd1.c   |   2 +-
  arch/arm/mm/dma-mapping.c  |  47 ++
  drivers/base/bus.c |   4 +-
  drivers/base/dd.c  |  10 +-
  drivers/base/platform.c|   2 +-
  drivers/base/power/domain.c|  70 ++-
  drivers/clk/samsung/clk-exynos4.c  |   1 +
  drivers/gpu/drm/exynos/exynos_drm_fimc.c   |   1 +
  drivers/gpu/drm/exynos/exynos_drm_fimd.c   |  26 +-
  drivers/gpu/drm/exynos/exynos_drm_g2d.c|   1 +
  drivers/gpu/drm/exynos/exynos_drm_gsc.c|   1 +
  drivers/gpu/drm/exynos/exynos_drm_rotator.c|   1 +
  drivers/gpu/drm/exynos/exynos_mixer.c  |   1 +
  drivers/iommu/exynos-iommu.c   | 663 +
  drivers/iommu/iommu.c  |   3 +
  drivers/media/platform/s5p-mfc/s5p_mfc.c   | 107 ++--
  drivers/pci/host/pci-mvebu.c   |   2 +-
  drivers/pci/host/pci-rcar-gen2.c   |   2 +-
  drivers/pci/host/pci-tegra.c   |   2 +-
  drivers/pci/host/pcie-rcar.c   |   2 +-
  drivers/soc/tegra/pmc.c|   2 +-
  include/dt-bindings/clock/exynos4.h|  10 +-
  include/linux/device.h |  12 +-
  include/linux/iommu.h  |   1 +
  include/linux/pm.h |   2 +
  include/linux/pm_domain.h  |  19 +
  33 files changed, 1016 insertions(+), 356 deletions(-)

This touches a lot of non-iommu stuff. What is your strategy on getting
this in, do you plan to get the non-iommu changes merged first or do you
want to collect the respective Acks and merge this all through one tree?


Those patches are posted as one patchset mainly to demonstrate how to get
everything to work together. I also posted this as a single patch series
to get some feedback from other iommu developers, especially all those
involved in the generic iommu dt bindings.

For merging, I will split them into smaller series and try to get
respective acks.

Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem

2014-08-19 Thread Marek Szyprowski

Hello,

On 2014-08-19 13:39, Andreas Färber wrote:

Hi Marek and Inki,

Am 19.08.2014 08:07, schrieb Marek Szyprowski:

On 2014-08-19 01:32, Joerg Roedel wrote:

On Tue, Aug 05, 2014 at 12:47:28PM +0200, Marek Szyprowski wrote:

[...]

   33 files changed, 1016 insertions(+), 356 deletions(-)

This touches a lot of non-iommu stuff. What is your strategy on getting
this in, do you plan to get the non-iommu changes merged first or do you
want to collect the respective Acks and merge this all through one tree?

Those patches are posted as one patchset mainly to demonstrate how to get
everything to work together. I also posted this as a single patch series
to get some feedback from other iommu developers, especially all those
involved in the generic iommu dt bindings.

For merging, I will split them into smaller series and try to get
respective acks.

I'm working on 5250 based Spring Chromebook and noticed that v3.17-rc1
got some more iommu support. With the new CONFIG_DRM_EXYNOS_IOMMU=y my
machine stops booting. So I'm wondering, is any of this a fix for 3.17,
or is all of this unrelated -next material?


This is probably a side effect of patch 
3170447c1f264d51b8d1f3898bf2588588a64fdc
(iommu/exynos: Select ARM_DMA_USE_IOMMU). It added selection of 
ARM_DMA_USE_IOMMU
symbol, on which IOMMU support in Exynos DRM subsystem depends. However 
selecting
this symbol is all that this patch does, without providing any code code 
which
implements real support for ARM DMA IOMMU integration, which is needed 
by Exynos
DRM driver. Please disable CONFIG_DRM_EXYNOS_IOMMU in kernel .config and 
your

system should be bootable again.


Also, are you or someone
working on the respective DT changes for Exynos5?


I can prepare DT changes for Exynos5 as well, but first I wanted to 
clarify if
everyone involved in generic IOMMU bindings and Exynos IOMMU driver 
agrees on my

proposal.

Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCH 04/29] drivers: base: add notifier for failed driver bind

2014-08-26 Thread Marek Szyprowski

Hello,

On 2014-08-25 22:05, Greg Kroah-Hartman wrote:

On Tue, Aug 05, 2014 at 12:47:32PM +0200, Marek Szyprowski wrote:

This patch adds support for getting a notify for failed device driver
bind, so all the items done in BUS_NOTIFY_BIND_DRIVER event can be
cleaned if the driver fails to bind.

But doesn't the bus know if the driver fails to bind, so why would a
notifier be needed here?  Can't it unwind any problems then?


Some other subsystems (like IOMMU) might register its own notifiers on
the given bus. Such notifier is called before driver probe
(BUS_NOTIFY_BIND_DRIVER event), so one can allocate some resources there.
However there is no way to do the cleanup if the driver fails to bind,
because no notifier is called in such case.


Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
  drivers/base/dd.c  | 10 +++---
  include/linux/device.h |  4 +++-
  2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index e4ffbcf..541a41f 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -237,10 +237,14 @@ static int driver_sysfs_add(struct device *dev)
return ret;
  }
  
-static void driver_sysfs_remove(struct device *dev)

+static void driver_sysfs_remove(struct device *dev, int failed)

I _hate_ having functions with a flag that does something different
depending on it.  If you _really_ need this, just make the notifier call
before calling this function, which should work just fine, right?


Ok, I will fix this. If I remember correctly I followed the 
driver_sysfs_add()

function pattern, which (surprisingly, especially when one considers only
the function name) also calls the bus notifiers.

Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 04/29] drivers: base: add notifier for failed driver bind

2014-08-26 Thread Marek Szyprowski

Hello,

On 2014-08-25 23:18, Joerg Roedel wrote:

On Tue, Aug 05, 2014 at 12:47:32PM +0200, Marek Szyprowski wrote:

+   if (failed  dev-bus)
+   blocking_notifier_call_chain(dev-bus-p-bus_notifier,
+BUS_NOTIFY_DRVBIND_FAILED, dev);
+

Why can't you just use the notifier for BUS_NOTIFY_UNBIND_DRIVER or
BUS_NOTIFY_UNBOUND_DRIVER when something goes wrong in driver
initialization?


Hmmm, you might be right. BUS_NOTIFY_UNBIND_DRIVER event happens before 
unbinding
the driver, but BUS_NOTIFY_UNBOUND_DRIVER is called when driver remove 
has been
finished, so it can be considered as a symmetrical pair for 
BUS_NOTIFY_BIND_DRIVER.
Driver which registered bus notifiers is mainly interested in doing 
right cleanup,

so the code executed for IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER and
IOMMU_GROUP_NOTIFY_DRVBIND_FAILED is same.

I will remove this additional event and simply add a call to
BUS_NOTIFY_UNBOUND_DRIVER event when driver probe fails.

Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 10/29] drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag

2014-08-31 Thread Marek Szyprowski

Hi Greg,

On 2014-08-05 12:47, Marek Szyprowski wrote:

This patch adds a new flags for device drivers. This flag instructs
kernel that the device driver does it own management of IOMMU assisted
IO address space translations, so no default dma-mapping structures
should be initialized.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
  include/linux/device.h | 2 ++
  1 file changed, 2 insertions(+)

diff --git a/include/linux/device.h b/include/linux/device.h
index 5f4ff02..2e62371 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -253,6 +253,8 @@ struct device_driver {
  
  /* disables bind/unbind via sysfs */

  #define DRIVER_SUPPRESS_BIND_ATTRS(1  0)
+/* driver uses own methods to manage IO address space */
+#define DRIVER_HAS_OWN_IOMMU_MANAGER   (1  1)
  
  extern int __must_check driver_register(struct device_driver *drv);

  extern void driver_unregister(struct device_driver *drv);


Could you comment if the approach of using flags in the struct driver
could be accepted? I've converted suppress_bind_attrs entry to flags to
avoid extending the structure, please see patch [PATCH 05/29] drivers:
convert suppress_bind_attrs parameter into flags.

Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 10/29] drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag

2014-09-01 Thread Marek Szyprowski

Hello,

On 2014-09-01 11:38, Arnd Bergmann wrote:

On Monday 01 September 2014 09:53:29 Marek Szyprowski wrote:

On 2014-09-01 09:07, Thierry Reding wrote:

On Mon, Sep 01, 2014 at 07:22:32AM +0200, Marek Szyprowski wrote:

Hi Greg,

On 2014-08-05 12:47, Marek Szyprowski wrote:

This patch adds a new flags for device drivers. This flag instructs
kernel that the device driver does it own management of IOMMU assisted
IO address space translations, so no default dma-mapping structures
should be initialized.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
include/linux/device.h | 2 ++
1 file changed, 2 insertions(+)

diff --git a/include/linux/device.h b/include/linux/device.h
index 5f4ff02..2e62371 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -253,6 +253,8 @@ struct device_driver {

/* disables bind/unbind via sysfs */

#define DRIVER_SUPPRESS_BIND_ATTRS   (1  0)
+/* driver uses own methods to manage IO address space */
+#define DRIVER_HAS_OWN_IOMMU_MANAGER   (1  1)

extern int __must_check driver_register(struct device_driver *drv);

extern void driver_unregister(struct device_driver *drv);

Could you comment if the approach of using flags in the struct driver
could be accepted? I've converted suppress_bind_attrs entry to flags to
avoid extending the structure, please see patch [PATCH 05/29] drivers:
convert suppress_bind_attrs parameter into flags.

Is this really necessary? What I did as part of an RFC series for Tegra
IOMMU support is keep this knowledge within the IOMMU driver rather than
export it to the driver core.i

The problem with embedding the list of drivers that you would need to update
it everytime when you modify or extend iommu support in the other drivers.
I've tried also other approach, like adding respective notifiers to
individual
drivers to initialize custom iommu support (or disable default iommu
mapping)
before iommu driver gets initialized, but such solution is in my opinion too
complex and hard to understand if one is not familiar will all this stuff.

All in all it turned out that the simplest and most generic way is to simply
add the flag to the driver core. Flags might be also used in the future
to model other kinds of dependencies between device drivers and/or driver
core.

I don't get it yet. I would expect that a driver doing its own management
of the iommu gets to use the linux/iommu.h interfaces, while a driver
using the default iommu setup uses linux/dma-mapping.h.


You are right.


Who do you think needs to set this flag, and who needs to read it?


In the proposed solution Exynos IOMMU driver creates a separate IO 
address space
for every client device in a system and binds it to the default 
dma-mapping space
for the given device. When drivers are doing its own management of IO 
address

space, instead of relying on what is available by default with dma-mapping
interface, this will require releasing of the previously created default
structures and resources. So this flag is set by the driver doing its own
management of io address space. The flags is then checked by Exynos 
IOMMU driver
to avoid creating the default dma-mapping address space for devices 
which driver

does its own management.

Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 10/29] drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag

2014-09-01 Thread Marek Szyprowski

Hello,

On 2014-09-01 13:56, Arnd Bergmann wrote:

On Monday 01 September 2014 12:47:08 Marek Szyprowski wrote:

Who do you think needs to set this flag, and who needs to read it?

In the proposed solution Exynos IOMMU driver creates a separate IO
address space
for every client device in a system and binds it to the default
dma-mapping space
for the given device. When drivers are doing its own management of IO
address
space, instead of relying on what is available by default with dma-mapping
interface, this will require releasing of the previously created default
structures and resources. So this flag is set by the driver doing its own
management of io address space. The flags is then checked by Exynos
IOMMU driver
to avoid creating the default dma-mapping address space for devices
which driver
does its own management.

I don't completely understand it yet. I would assume the device
to be added to the default domain at device creation time
(of_platform_populate), way before we know which device driver
is going to be used. How can this prevent the iommu driver
from doing the association with the domain?


of_platform_populate() is too early to do the association, because that 
time the

exynos iommu driver is even not yet probed.

The association with default dma-mapping domain is done in
IOMMU_GROUP_NOTIFY_BIND_DRIVER notifier, just before binding the driver 
to the
given device. This way iommu driver can check dev-driver-flags and 
skip creating

default dma-mapping domain if driver announces that it wants to handle it by
itself.

Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH 0/7] Introduce automatic DMA configuration for IOMMU masters

2014-09-02 Thread Marek Szyprowski

Hi Will,

On 2014-08-29 17:54, Will Deacon wrote:

This patch series is an RFC to implement IOMMU master configuration into
of_dma_configure. I haven't yet ported any IOMMU drivers to it, so it
remains untested, but I wanted to get some early feedback to ensure that
this doesn't end up going in the wrong direction.

The idea comes out of my understanding following discussions with Arnd
and David at Kernel Summit / LinuxCon in Chicago. Essentially:

   - Allow IOMMUs to be probed early and set up per-instance data on their
 of_node

   - Add a new callback to the iommu_ops structure for adding a device
 with a set of opaque IDs (e.g. Stream IDs or Requester IDs)

   - Add an of_iommu_configure function, called from of_dma_configure,
 which registers the master IDs with the correspond IOMMU before
 probing the master itself

   - Where applicable, create an IOMMU domain per device and swizzle the
 DMA ops for that device to use the IOMMU variants.

I haven't bothered doing anything clever with the DMA masks yet, so I
wouldn't be surprised if we end up chewing through tonnes of memory
allocating IOMMU domains that are far too big at the moment. Again, this
is just an RFC and I'd welcome comments on the general direction of the
series.


Thanks for your patches, I wasn't aware the fact that you are working on
this. When do you plan to send a second version? I would like to rebase
my Exynos IOMMU patches (https://lkml.org/lkml/2014/8/5/183) on top of
your work, but I wonder if I should select this version as a base or wait
a bit for an update.

Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH 0/7] Introduce automatic DMA configuration for IOMMU masters

2014-09-02 Thread Marek Szyprowski

Hi Will,

On 2014-09-02 10:31, Will Deacon wrote:

On Tue, Sep 02, 2014 at 07:26:01AM +0100, Marek Szyprowski wrote:

On 2014-08-29 17:54, Will Deacon wrote:

This patch series is an RFC to implement IOMMU master configuration into
of_dma_configure. I haven't yet ported any IOMMU drivers to it, so it
remains untested, but I wanted to get some early feedback to ensure that
this doesn't end up going in the wrong direction.

The idea comes out of my understanding following discussions with Arnd
and David at Kernel Summit / LinuxCon in Chicago. Essentially:

- Allow IOMMUs to be probed early and set up per-instance data on their
  of_node

- Add a new callback to the iommu_ops structure for adding a device
  with a set of opaque IDs (e.g. Stream IDs or Requester IDs)

- Add an of_iommu_configure function, called from of_dma_configure,
  which registers the master IDs with the correspond IOMMU before
  probing the master itself

- Where applicable, create an IOMMU domain per device and swizzle the
  DMA ops for that device to use the IOMMU variants.

I haven't bothered doing anything clever with the DMA masks yet, so I
wouldn't be surprised if we end up chewing through tonnes of memory
allocating IOMMU domains that are far too big at the moment. Again, this
is just an RFC and I'd welcome comments on the general direction of the
series.

Thanks for your patches, I wasn't aware the fact that you are working on
this. When do you plan to send a second version? I would like to rebase
my Exynos IOMMU patches (https://lkml.org/lkml/2014/8/5/183) on top of
your work, but I wonder if I should select this version as a base or wait
a bit for an update.

I'll try and get something out today/tomorrow depending on how easily the
review comments fall out. It would be really great if you get an IOMMU
working with this (I was going to look at the ARM SMMU once this stops
moving)


Great, I will wait then for v2.


  -- I have concerns that allocating one domain per master might be
too much, but it's hard to tell without an IOMMU driver ported over.


One domain per master is IMHO a sane default configuration. The only default
alternative I see is to have only one domain (related with dma-mapping
subsystem) and bind all devices to it. However I really don't see any
disadvantage of having separate domain per each master and such 
configuration

gives devices better separation.

However we also need to figure out how to let drivers to make their own
configuration, like it is required by Exynos DRM subsystem, which consist
of several devices, each having its own IOMMU controller, but for
convenience those drivers assume that they all have been bound to the same,
single domain.

Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH 0/7] Introduce automatic DMA configuration for IOMMU masters

2014-09-02 Thread Marek Szyprowski

Hi Arnd,

On 2014-09-02 10:56, Arnd Bergmann wrote:

On Tuesday 02 September 2014 10:48:02 Marek Szyprowski wrote:

   -- I have concerns that allocating one domain per master might be
too much, but it's hard to tell without an IOMMU driver ported over.

One domain per master is IMHO a sane default configuration. The only default
alternative I see is to have only one domain (related with dma-mapping
subsystem) and bind all devices to it. However I really don't see any
disadvantage of having separate domain per each master and such
configuration
gives devices better separation.

I was expecting that the dma-mapping implementation would by default use
one domain for all devices, since that is what the simpler IOMMUs without
domain support have to do anyway.

For isolation purposes, it can only help to have more domains, but
I would guess that there is some space overhead in maintaining lots
of page tables.


I'm okay with both approaches (separate domain for each device vs. single
common domain for all devices). Maybe this can be some kind of Kconfig
option added to DMA debugging? Separation might be really helpful when
debugging strange device behavior.


However we also need to figure out how to let drivers to make their own
configuration, like it is required by Exynos DRM subsystem, which consist
of several devices, each having its own IOMMU controller, but for
convenience those drivers assume that they all have been bound to the same,
single domain.

IIRC with the way we ended up putting the mask into the iommu descriptor of
the ARM SMMU, you can put multiple devices into the same iommu group, and
have them automatically share a domain.

I don't know if the same would work for the Samsung implementation.


The question is how to transfer such information from the device 
drivers, that
need/benefit from such configuration to iommu driver, which does all the 
setup?
This is something completely internal to particular drivers and should 
not be

exported to device tree or userspace. Thierry suggested to hardcode this
information in the iommu driver, but I'm looking for other approaches.
Maybe simply releasing device from the default dma-mapping domain before
attaching to custom one will be the easiest solution.

Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH 0/7] Introduce automatic DMA configuration for IOMMU masters

2014-09-02 Thread Marek Szyprowski

Hi Will,

On 2014-09-02 12:57, Will Deacon wrote:

On Tue, Sep 02, 2014 at 11:42:13AM +0100, Marek Szyprowski wrote:

On 2014-09-02 10:56, Arnd Bergmann wrote:

On Tuesday 02 September 2014 10:48:02 Marek Szyprowski wrote:

-- I have concerns that allocating one domain per master might be
too much, but it's hard to tell without an IOMMU driver ported over.

One domain per master is IMHO a sane default configuration. The only default
alternative I see is to have only one domain (related with dma-mapping
subsystem) and bind all devices to it. However I really don't see any
disadvantage of having separate domain per each master and such
configuration
gives devices better separation.

I was expecting that the dma-mapping implementation would by default use
one domain for all devices, since that is what the simpler IOMMUs without
domain support have to do anyway.

For isolation purposes, it can only help to have more domains, but
I would guess that there is some space overhead in maintaining lots
of page tables.

I'm okay with both approaches (separate domain for each device vs. single
common domain for all devices). Maybe this can be some kind of Kconfig
option added to DMA debugging? Separation might be really helpful when
debugging strange device behavior.

One potential problem with a single domain is when you have multiple
instances of a given IOMMU, each with different hardware restrictions.
Then you can end up with multiple sets of page tables for the domain
which, although not impossible to work with, is a bit of a mess.


Maybe the default dma-mapping domain should be one per a given IOMMU 
instance?

This will simplify a lot of things in such case.


I think having one domain per IOMMU instance would make the most sense,
but then you have to teach more of the stack about the IOMMU topology. I
think we'll get there in the end, but that's a little way off right now.


Right, those seems to be a details.

Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH 0/7] Introduce automatic DMA configuration for IOMMU masters

2014-09-02 Thread Marek Szyprowski

Hi Arnd,

On 2014-09-02 14:22, Arnd Bergmann wrote:

On Tuesday 02 September 2014 12:42:13 Marek Szyprowski wrote:

On 2014-09-02 10:56, Arnd Bergmann wrote:

On Tuesday 02 September 2014 10:48:02 Marek Szyprowski wrote:

-- I have concerns that allocating one domain per master might be
too much, but it's hard to tell without an IOMMU driver ported over.

One domain per master is IMHO a sane default configuration. The only default
alternative I see is to have only one domain (related with dma-mapping
subsystem) and bind all devices to it. However I really don't see any
disadvantage of having separate domain per each master and such
configuration
gives devices better separation.

I was expecting that the dma-mapping implementation would by default use
one domain for all devices, since that is what the simpler IOMMUs without
domain support have to do anyway.

For isolation purposes, it can only help to have more domains, but
I would guess that there is some space overhead in maintaining lots
of page tables.

I'm okay with both approaches (separate domain for each device vs. single
common domain for all devices). Maybe this can be some kind of Kconfig
option added to DMA debugging? Separation might be really helpful when
debugging strange device behavior.

We should probably support the iommu=strict command line option that some
other architectures have. This is mainly meant to ensure that IOTLBs
are shot down as soon as the driver unmaps some memory, which you often
want to avoid for performance reasons.

The iommu driver itself can then decide to also use separate domains
for iommu=strict but a shared domain otherwise.

For hardware on which the shared domain is hard to do, the driver might
always use separate domains.


Just to let you know, lazy unmapping is not yet implemented in ARM 
dma-mapping

implementation based on IOMMU.


However we also need to figure out how to let drivers to make their own
configuration, like it is required by Exynos DRM subsystem, which consist
of several devices, each having its own IOMMU controller, but for
convenience those drivers assume that they all have been bound to the same,
single domain.

IIRC with the way we ended up putting the mask into the iommu descriptor of
the ARM SMMU, you can put multiple devices into the same iommu group, and
have them automatically share a domain.

I don't know if the same would work for the Samsung implementation.

The question is how to transfer such information from the device
drivers, that
need/benefit from such configuration to iommu driver, which does all the
setup?
This is something completely internal to particular drivers and should
not be
exported to device tree or userspace. Thierry suggested to hardcode this
information in the iommu driver, but I'm looking for other approaches.
Maybe simply releasing device from the default dma-mapping domain before
attaching to custom one will be the easiest solution.

For the ARM SMMU, the problem is that there is not necessarily a good way
to partition the masters into IOMMU groups automatically, therefore we
want to provide some hints in DT. On a machine that can have more domains
than it has masters, this is not a problem and we can always use an
all-ones mask, but for a machine on which this is not the case, the
problem is simplified a lot of we hardcode the masks in a way that can
always work, putting multiple devices into an iommu group if necessary.


Well, I was talking about the Exynos IOMMU case, where there are no hw
restrictions and grouping is done just to make things easier for the Exynos
DRM drivers (a buffer gets the same DMA address for all devices, which
are a part of virtual Exynos DRM device).


This is similar to how we do things for pinctrl, where you might have
a theoretically endless space of options to set stuff up, but we
can simplify it by defining the useful configurations.


Right, if hardware is limited, a sane working configuration is something 
that

should be encoded in device tree.

Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH 0/7] Introduce automatic DMA configuration for IOMMU masters

2014-09-02 Thread Marek Szyprowski


On 2014-09-02 14:46, Arnd Bergmann wrote:

On Tuesday 02 September 2014 14:30:36 Marek Szyprowski wrote:

However we also need to figure out how to let drivers to make their own
configuration, like it is required by Exynos DRM subsystem, which consist
of several devices, each having its own IOMMU controller, but for
convenience those drivers assume that they all have been bound to the same,
single domain.

IIRC with the way we ended up putting the mask into the iommu descriptor of
the ARM SMMU, you can put multiple devices into the same iommu group, and
have them automatically share a domain.

I don't know if the same would work for the Samsung implementation.

The question is how to transfer such information from the device
drivers, that
need/benefit from such configuration to iommu driver, which does all the
setup?
This is something completely internal to particular drivers and should
not be
exported to device tree or userspace. Thierry suggested to hardcode this
information in the iommu driver, but I'm looking for other approaches.
Maybe simply releasing device from the default dma-mapping domain before
attaching to custom one will be the easiest solution.

For the ARM SMMU, the problem is that there is not necessarily a good way
to partition the masters into IOMMU groups automatically, therefore we
want to provide some hints in DT. On a machine that can have more domains
than it has masters, this is not a problem and we can always use an
all-ones mask, but for a machine on which this is not the case, the
problem is simplified a lot of we hardcode the masks in a way that can
always work, putting multiple devices into an iommu group if necessary.

Well, I was talking about the Exynos IOMMU case, where there are no hw
restrictions and grouping is done just to make things easier for the Exynos
DRM drivers (a buffer gets the same DMA address for all devices, which
are a part of virtual Exynos DRM device).

Does that mean you don't actually need to use multiple contexts here and
could actually just use the normal dma-mapping interface if there is
a way to ensure the mappings are always shared across these masters?


Well, a default, shared single domain for dma-mapping interface will work
with Exynos DRM and its multiple masters, although I never thought about
such configuration.


Or do you need this in addition to being able to use multiple masters
so you can have multiple rendering contexts in user space?


Such advanced IO space management is not yet implemented.

However there are also devices (like multimedia codec - exynos mfc and 
camera

capture subsystem exynos isp), which have limited DMA/IO window (256MiB in
case of video codec), so they will still need to use their own separate 
domain.


Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH v2 3/7] iommu: add new iommu_ops callback for adding an OF device

2014-09-10 Thread Marek Szyprowski

Hello,

On 2014-09-02 19:56, Will Deacon wrote:

This patch adds a new function to the iommu_ops structure to allow an
OF device to be added to a specific IOMMU instance using the recently
merged generic devicetree binding for IOMMUs. The callback (of_xlate)
takes a struct device representing the master and an of_phandle_args
representing the IOMMU and the correspondong IDs for the new master.

Signed-off-by: Will Deacon will.dea...@arm.com
---
  include/linux/iommu.h | 5 +
  1 file changed, 5 insertions(+)

diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index fdddb14cd8f5..3e766b85daa3 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -21,6 +21,7 @@
  
  #include linux/errno.h

  #include linux/err.h
+#include linux/of.h
  #include linux/types.h
  #include trace/events/iommu.h
  
@@ -136,6 +137,10 @@ struct iommu_ops {

/* Get the numer of window per domain */
u32 (*domain_get_windows)(struct iommu_domain *domain);
  
+#ifdef CONFIG_OF_IOMMU

+   int (*of_xlate)(struct device *dev, struct of_phandle_args *args);


If I understand correctly how it is designed to work, then it should be:

struct iommu_data *(*of_xlate)(struct device *dev, struct 
of_phandle_args *args);



+#endif
+
unsigned long pgsize_bitmap;
  };
  


Best regards
--
Marek Szyprowski, PhD
Samsung RD Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 06/18] iommu: exynos: don't read version register on every tlb operation

2014-09-16 Thread Marek Szyprowski
This patch removes reading of REG_MMU_VERSION register on every tlb
operation and caches SYSMMU version in driver's internal data.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 13 +
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index d037e87a1fe5..73499b05e62e 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -212,6 +212,7 @@ struct sysmmu_drvdata {
spinlock_t lock;
struct iommu_domain *domain;
phys_addr_t pgtable;
+   int version;
 };
 
 static bool set_sysmmu_active(struct sysmmu_drvdata *data)
@@ -238,11 +239,6 @@ static void sysmmu_unblock(void __iomem *sfrbase)
__raw_writel(CTRL_ENABLE, sfrbase + REG_MMU_CTRL);
 }
 
-static unsigned int __raw_sysmmu_version(struct sysmmu_drvdata *data)
-{
-   return MMU_RAW_VER(__raw_readl(data-sfrbase + REG_MMU_VERSION));
-}
-
 static bool sysmmu_block(void __iomem *sfrbase)
 {
int i = 120;
@@ -402,7 +398,7 @@ static void __sysmmu_init_config(struct sysmmu_drvdata 
*data)
unsigned int cfg = CFG_LRU | CFG_QOS(15);
unsigned int ver;
 
-   ver = __raw_sysmmu_version(data);
+   ver = MMU_RAW_VER(__raw_readl(data-sfrbase + REG_MMU_VERSION));
if (MMU_MAJ_VER(ver) == 3) {
if (MMU_MIN_VER(ver) = 2) {
cfg |= CFG_FLPDCACHE;
@@ -416,6 +412,7 @@ static void __sysmmu_init_config(struct sysmmu_drvdata 
*data)
}
 
__raw_writel(cfg, data-sfrbase + REG_MMU_CFG);
+   data-version = ver;
 }
 
 static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data)
@@ -525,7 +522,7 @@ static bool exynos_sysmmu_disable(struct device *dev)
 static void __sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
  sysmmu_iova_t iova)
 {
-   if (__raw_sysmmu_version(data) == MAKE_MMU_VER(3, 3))
+   if (data-version == MAKE_MMU_VER(3, 3))
__raw_writel(iova | 0x1, data-sfrbase + REG_MMU_FLUSH_ENTRY);
 }
 
@@ -574,7 +571,7 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, 
sysmmu_iova_t iova,
 * 1MB page can be cached in one of all sets.
 * 64KB page can be one of 16 consecutive sets.
 */
-   if (MMU_MAJ_VER(__raw_sysmmu_version(data)) == 2)
+   if (MMU_MAJ_VER(data-version) == 2)
num_inv = min_t(unsigned int, size / PAGE_SIZE, 64);
 
if (sysmmu_block(data-sfrbase)) {
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 04/18] clk: exynos: add missing smmu_g2d clock and update comments

2014-09-16 Thread Marek Szyprowski
This patch adds missing smmu_g2d clock implementation and updates
comment about Exynos4 clocks from 278-282 range. Those clocks are
available on all Exynos4 SoC series, so the misleading comment has been
removed.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
Acked-by: Tomasz Figa t.f...@samsung.com
---
 drivers/clk/samsung/clk-exynos4.c   |  1 +
 include/dt-bindings/clock/exynos4.h | 10 +-
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c 
b/drivers/clk/samsung/clk-exynos4.c
index ac163d7f5bc3..12a7cc3b5953 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -1183,6 +1183,7 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] 
__initdata = {
GATE(CLK_SPI1_ISP, spi1_isp, aclk200, E4X12_GATE_ISP1, 13,
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
GATE(CLK_G2D, g2d, aclk200, GATE_IP_DMC, 23, 0, 0),
+   GATE(CLK_SMMU_G2D, smmu_g2d, aclk200, GATE_IP_DMC, 24, 0, 0),
GATE(CLK_TMU_APBIF, tmu_apbif, aclk100, E4X12_GATE_IP_PERIR, 17, 0,
0),
 };
diff --git a/include/dt-bindings/clock/exynos4.h 
b/include/dt-bindings/clock/exynos4.h
index 459bd2bd411f..fb9816354079 100644
--- a/include/dt-bindings/clock/exynos4.h
+++ b/include/dt-bindings/clock/exynos4.h
@@ -115,11 +115,11 @@
 #define CLK_SMMU_MFCR  275
 #define CLK_G3D276
 #define CLK_G2D277
-#define CLK_ROTATOR278 /* Exynos4210 only */
-#define CLK_MDMA   279 /* Exynos4210 only */
-#define CLK_SMMU_G2D   280 /* Exynos4210 only */
-#define CLK_SMMU_ROTATOR   281 /* Exynos4210 only */
-#define CLK_SMMU_MDMA  282 /* Exynos4210 only */
+#define CLK_ROTATOR278
+#define CLK_MDMA   279
+#define CLK_SMMU_G2D   280
+#define CLK_SMMU_ROTATOR   281
+#define CLK_SMMU_MDMA  282
 #define CLK_FIMD0  283
 #define CLK_MIE0   284
 #define CLK_MDNIE0 285 /* Exynos4412 only */
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 00/18] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem

2014-09-16 Thread Marek Szyprowski
Hello Everyone,

This is yet another attempt to finally make Exynos SYSMMU driver fully
integrated with DMA-mapping subsystem.

Previous approach is available here: https://lkml.org/lkml/2014/8/5/183

I meantime, there have been a discussion about the way the iommu driver
should be integrated with dma-mapping subsystem, which resulted in [RFC
PATCH v3 0/7] Introduce automatic DMA configuration for IOMMU masters
patches prepared by Will Deacon:
http://www.spinics.net/lists/arm-kernel/msg362076.html 
Those patches removed the need to use bus-specific notifiers for
initialization.

Main changes since previous version of my patches:

1. rebased onto [RFC PATCH v3 0/7] Introduce automatic DMA
configuration for IOMMU masters patches, changed initialization from
bus notifiers to DT related callbacks

2. removed support for separate IO address spaces - this will be
discussed separately after the basic support gets merged

3. removed support for power domain notifier-based runtime power
management - this also will be discussed separately later

I hope that the driver with above changes will be easier to be merged to
v3.18.

Best regards
Marek Szyprowski
Samsung RD Institute Poland



Patch summary:

Marek Szyprowski (18):
  arm: dma-mapping: arm_iommu_attach_device: automatically set
max_seg_size
  arm: exynos: bind power domains earlier, on device creation
  drm: exynos: detach from default dma-mapping domain on init
  clk: exynos: add missing smmu_g2d clock and update comments
  ARM: DTS: Exynos4: add System MMU nodes
  iommu: exynos: don't read version register on every tlb operation
  iommu: exynos: remove unused functions
  iommu: exynos: remove useless spinlock
  iommu: exynos: refactor function parameters to simplify code
  iommu: exynos: remove unused functions, part 2
  iommu: exynos: remove useless device_add/remove callbacks
  iommu: exynos: add support for binding more than one sysmmu to master
device
  iommu: exynos: add support for runtime_pm
  iommu: exynos: rename variables to reflect their purpose
  iommu: exynos: document internal structures
  iommu: exynos: remove excessive includes and sort others
alphabetically
  iommu: exynos: init from dt-specific callback instead of initcall
  iommu: exynos: add callback for initializing devices from device tree

 arch/arm/boot/dts/exynos4.dtsi| 117 +++
 arch/arm/boot/dts/exynos4210.dtsi |  23 ++
 arch/arm/boot/dts/exynos4x12.dtsi |  82 +
 arch/arm/mach-exynos/pm_domains.c |  12 +-
 arch/arm/mm/dma-mapping.c |  16 +
 drivers/clk/samsung/clk-exynos4.c |   1 +
 drivers/gpu/drm/exynos/exynos_drm_iommu.c |   3 +
 drivers/iommu/exynos-iommu.c  | 494 ++
 include/dt-bindings/clock/exynos4.h   |  10 +-
 9 files changed, 483 insertions(+), 275 deletions(-)

-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 01/18] arm: dma-mapping: arm_iommu_attach_device: automatically set max_seg_size

2014-09-16 Thread Marek Szyprowski
If device has no max_seg_size set, we assume that there is no limit and
force it to DMA_BIT_MASK(32) to always use contiguous mappings in DMA
address space.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 arch/arm/mm/dma-mapping.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index bcd5f836f27e..84705e24571b 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -2050,6 +2050,22 @@ int arm_iommu_attach_device(struct device *dev,
 {
int err;
 
+   /*
+* if device has no max_seg_size set, we assume that there is no limit
+* and force it to DMA_BIT_MASK(32) to always use contiguous mappings
+* in DMA address space
+*/
+   if (!dev-dma_parms) {
+   dev-dma_parms = kzalloc(sizeof(*dev-dma_parms), GFP_KERNEL);
+   if (!dev-dma_parms)
+   return -ENOMEM;
+   }
+   if (!dev-dma_parms-max_segment_size) {
+   err = dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
+   if (err)
+   return err;
+   }
+
err = iommu_attach_device(mapping-domain, dev);
if (err)
return err;
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 02/18] arm: exynos: bind power domains earlier, on device creation

2014-09-16 Thread Marek Szyprowski
This patches change initialization time of power domain driver from client
device driver bind to device creation. This lets other core drivers to
register power domain notifiers before client driver is bound.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 arch/arm/mach-exynos/pm_domains.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-exynos/pm_domains.c 
b/arch/arm/mach-exynos/pm_domains.c
index fd76e1b5a471..1d368a26528c 100644
--- a/arch/arm/mach-exynos/pm_domains.c
+++ b/arch/arm/mach-exynos/pm_domains.c
@@ -159,13 +159,13 @@ static int exynos_pm_notifier_call(struct notifier_block 
*nb,
struct device *dev = data;
 
switch (event) {
-   case BUS_NOTIFY_BIND_DRIVER:
+   case BUS_NOTIFY_ADD_DEVICE:
if (dev-of_node)
exynos_read_domain_from_dt(dev);
 
break;
 
-   case BUS_NOTIFY_UNBOUND_DRIVER:
+   case BUS_NOTIFY_DEL_DEVICE:
exynos_remove_device_from_domain(dev);
 
break;
@@ -177,6 +177,13 @@ static struct notifier_block platform_nb = {
.notifier_call = exynos_pm_notifier_call,
 };
 
+static int exynos_pm_domain_add(struct device *dev, void *priv)
+{
+   if (dev-of_node)
+   exynos_read_domain_from_dt(dev);
+   return 0;
+}
+
 static __init int exynos4_pm_init_power_domain(void)
 {
struct platform_device *pdev;
@@ -236,6 +243,7 @@ no_clk:
}
 
bus_register_notifier(platform_bus_type, platform_nb);
+   bus_for_each_dev(platform_bus_type, NULL, NULL, exynos_pm_domain_add);
 
return 0;
 }
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 05/18] ARM: DTS: Exynos4: add System MMU nodes

2014-09-16 Thread Marek Szyprowski
This patch adds System MMU nodes that are specific to Exynos4210/4x12 series.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 arch/arm/boot/dts/exynos4.dtsi| 117 ++
 arch/arm/boot/dts/exynos4210.dtsi |  23 
 arch/arm/boot/dts/exynos4x12.dtsi |  82 ++
 3 files changed, 222 insertions(+)

diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index e0278ecbc816..bfc19ec5 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -174,6 +174,7 @@
clock-names = fimc, sclk_fimc;
samsung,power-domain = pd_cam;
samsung,sysreg = sys_reg;
+   iommus = sysmmu_fimc0;
status = disabled;
};
 
@@ -185,6 +186,7 @@
clock-names = fimc, sclk_fimc;
samsung,power-domain = pd_cam;
samsung,sysreg = sys_reg;
+   iommus = sysmmu_fimc1;
status = disabled;
};
 
@@ -196,6 +198,7 @@
clock-names = fimc, sclk_fimc;
samsung,power-domain = pd_cam;
samsung,sysreg = sys_reg;
+   iommus = sysmmu_fimc2;
status = disabled;
};
 
@@ -207,6 +210,7 @@
clock-names = fimc, sclk_fimc;
samsung,power-domain = pd_cam;
samsung,sysreg = sys_reg;
+   iommus = sysmmu_fimc3;
status = disabled;
};
 
@@ -395,6 +399,8 @@
clocks = clock CLK_MFC;
clock-names = mfc;
status = disabled;
+   iommus = sysmmu_mfc_l, sysmmu_mfc_r;
+   iommu-names = left, right;
};
 
serial_0: serial@1380 {
@@ -643,6 +649,117 @@
clock-names = sclk_fimd, fimd;
samsung,power-domain = pd_lcd0;
samsung,sysreg = sys_reg;
+   iommus = sysmmu_fimd0;
status = disabled;
};
+
+   sysmmu_mfc_l: sysmmu@1362 {
+   compatible = samsung,exynos-sysmmu;
+   reg = 0x1362 0x1000;
+   interrupt-parent = combiner;
+   interrupts = 5 5;
+   clock-names = sysmmu, master;
+   clocks = clock CLK_SMMU_MFCL, clock CLK_MFC;
+   samsung,power-domain = pd_mfc;
+   #iommu-cells = 0;
+   };
+
+   sysmmu_mfc_r: sysmmu@1363 {
+   compatible = samsung,exynos-sysmmu;
+   reg = 0x1363 0x1000;
+   interrupt-parent = combiner;
+   interrupts = 5 6;
+   clock-names = sysmmu, master;
+   clocks = clock CLK_SMMU_MFCR, clock CLK_MFC;
+   samsung,power-domain = pd_mfc;
+   #iommu-cells = 0;
+   };
+
+   sysmmu_tv: sysmmu@12E2 {
+   compatible = samsung,exynos-sysmmu;
+   reg = 0x12E2 0x1000;
+   interrupt-parent = combiner;
+   interrupts = 5 4;
+   clock-names = sysmmu, master;
+   clocks = clock CLK_SMMU_TV, clock CLK_MIXER;
+   samsung,power-domain = pd_tv;
+   #iommu-cells = 0;
+   };
+
+   sysmmu_fimc0: sysmmu@11A2 {
+   compatible = samsung,exynos-sysmmu;
+   reg = 0x11A2 0x1000;
+   interrupt-parent = combiner;
+   interrupts = 4 2;
+   clock-names = sysmmu, master;
+   clocks = clock CLK_SMMU_FIMC0, clock CLK_FIMC0;
+   samsung,power-domain = pd_cam;
+   #iommu-cells = 0;
+   };
+
+   sysmmu_fimc1: sysmmu@11A3 {
+   compatible = samsung,exynos-sysmmu;
+   reg = 0x11A3 0x1000;
+   interrupt-parent = combiner;
+   interrupts = 4 3;
+   clock-names = sysmmu, master;
+   clocks = clock CLK_SMMU_FIMC1, clock CLK_FIMC1;
+   samsung,power-domain = pd_cam;
+   #iommu-cells = 0;
+   };
+
+   sysmmu_fimc2: sysmmu@11A4 {
+   compatible = samsung,exynos-sysmmu;
+   reg = 0x11A4 0x1000;
+   interrupt-parent = combiner;
+   interrupts = 4 4;
+   clock-names = sysmmu, master;
+   clocks = clock CLK_SMMU_FIMC2, clock CLK_FIMC2;
+   samsung,power-domain = pd_cam;
+   #iommu-cells = 0;
+   };
+
+   sysmmu_fimc3: sysmmu@11A5 {
+   compatible = samsung,exynos-sysmmu;
+   reg = 0x11A5 0x1000;
+   interrupt-parent = combiner;
+   interrupts = 4 5;
+   clock-names = sysmmu, master

[PATCH v2 07/18] iommu: exynos: remove unused functions

2014-09-16 Thread Marek Szyprowski
This patch removes two unneeded functions, which are not a part of
generic IOMMU API and were never used by any other driver.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 31 ---
 1 file changed, 31 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 73499b05e62e..91feeca56abc 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -490,13 +490,6 @@ static int __exynos_sysmmu_enable(struct device *dev, 
phys_addr_t pgtable,
return ret;
 }
 
-int exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable)
-{
-   BUG_ON(!memblock_is_memory(pgtable));
-
-   return __exynos_sysmmu_enable(dev, pgtable, NULL);
-}
-
 static bool exynos_sysmmu_disable(struct device *dev)
 {
unsigned long flags;
@@ -588,30 +581,6 @@ static void sysmmu_tlb_invalidate_entry(struct device 
*dev, sysmmu_iova_t iova,
spin_unlock_irqrestore(data-lock, flags);
 }
 
-void exynos_sysmmu_tlb_invalidate(struct device *dev)
-{
-   struct exynos_iommu_owner *owner = dev-archdata.iommu;
-   unsigned long flags;
-   struct sysmmu_drvdata *data;
-
-   data = dev_get_drvdata(owner-sysmmu);
-
-   spin_lock_irqsave(data-lock, flags);
-   if (is_sysmmu_active(data)) {
-   if (!IS_ERR(data-clk_master))
-   clk_enable(data-clk_master);
-   if (sysmmu_block(data-sfrbase)) {
-   __sysmmu_tlb_invalidate(data-sfrbase);
-   sysmmu_unblock(data-sfrbase);
-   }
-   if (!IS_ERR(data-clk_master))
-   clk_disable(data-clk_master);
-   } else {
-   dev_dbg(dev, disabled. Skipping TLB invalidation\n);
-   }
-   spin_unlock_irqrestore(data-lock, flags);
-}
-
 static int __init exynos_sysmmu_probe(struct platform_device *pdev)
 {
int irq, ret;
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 10/18] iommu: exynos: remove unused functions, part 2

2014-09-16 Thread Marek Szyprowski
After refactoring functions to use pointer to struct sysmmu_drvdata
directly, some functions became useless and thus never used, so remove
them completely.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 43 ---
 1 file changed, 43 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index ef30890f4069..b271348a4ec1 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -457,49 +457,6 @@ static int __sysmmu_enable(struct sysmmu_drvdata *data,
return ret;
 }
 
-/* __exynos_sysmmu_enable: Enables System MMU
- *
- * returns -error if an error occurred and System MMU is not enabled,
- * 0 if the System MMU has been just enabled and 1 if System MMU was already
- * enabled before.
- */
-static int __exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable,
- struct iommu_domain *domain)
-{
-   int ret = 0;
-   unsigned long flags;
-   struct exynos_iommu_owner *owner = dev-archdata.iommu;
-   struct sysmmu_drvdata *data;
-
-   BUG_ON(!has_sysmmu(dev));
-
-   data = dev_get_drvdata(owner-sysmmu);
-
-   ret = __sysmmu_enable(data, pgtable, domain);
-   if (ret = 0)
-   data-master = dev;
-
-   return ret;
-}
-
-static bool exynos_sysmmu_disable(struct device *dev)
-{
-   unsigned long flags;
-   bool disabled = true;
-   struct exynos_iommu_owner *owner = dev-archdata.iommu;
-   struct sysmmu_drvdata *data;
-
-   BUG_ON(!has_sysmmu(dev));
-
-   data = dev_get_drvdata(owner-sysmmu);
-
-   disabled = __sysmmu_disable(data);
-   if (disabled)
-   data-master = NULL;
-
-   return disabled;
-}
-
 static void __sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
  sysmmu_iova_t iova)
 {
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 08/18] iommu: exynos: remove useless spinlock

2014-09-16 Thread Marek Szyprowski
This patch removes useless spinlocks and other unused members from
struct exynos_iommu_owner. There is no point is protecting this
structure by spinlock because content of this structure doesn't change
and other structures have their own spinlocks.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 11 ---
 1 file changed, 11 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 91feeca56abc..ae2703ed91d8 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -189,9 +189,6 @@ struct exynos_iommu_owner {
struct list_head client; /* entry of exynos_iommu_domain.clients */
struct device *dev;
struct device *sysmmu;
-   struct iommu_domain *domain;
-   void *vmm_data; /* IO virtual memory manager's data */
-   spinlock_t lock;/* Lock to preserve consistency of System MMU */
 };
 
 struct exynos_iommu_domain {
@@ -477,16 +474,12 @@ static int __exynos_sysmmu_enable(struct device *dev, 
phys_addr_t pgtable,
 
BUG_ON(!has_sysmmu(dev));
 
-   spin_lock_irqsave(owner-lock, flags);
-
data = dev_get_drvdata(owner-sysmmu);
 
ret = __sysmmu_enable(data, pgtable, domain);
if (ret = 0)
data-master = dev;
 
-   spin_unlock_irqrestore(owner-lock, flags);
-
return ret;
 }
 
@@ -499,16 +492,12 @@ static bool exynos_sysmmu_disable(struct device *dev)
 
BUG_ON(!has_sysmmu(dev));
 
-   spin_lock_irqsave(owner-lock, flags);
-
data = dev_get_drvdata(owner-sysmmu);
 
disabled = __sysmmu_disable(data);
if (disabled)
data-master = NULL;
 
-   spin_unlock_irqrestore(owner-lock, flags);
-
return disabled;
 }
 
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 12/18] iommu: exynos: add support for binding more than one sysmmu to master device

2014-09-16 Thread Marek Szyprowski
This patch adds support for assigning more than one SYSMMU controller to
the master device. This has been achieved simply by chaning the struct
device pointer in struct exynos_iommu_owner into the list of struct
sysmmu_drvdata of all controllers assigned to the given master device.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 1b3f00726cd4..cf36cdecf335 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -186,7 +186,7 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
 
 /* attached to dev.archdata.iommu of the master device */
 struct exynos_iommu_owner {
-   struct device *sysmmu;
+   struct list_head clients;
 };
 
 struct exynos_iommu_domain {
@@ -207,6 +207,7 @@ struct sysmmu_drvdata {
spinlock_t lock;
struct iommu_domain *domain;
struct list_head domain_node;
+   struct list_head owner_node;
phys_addr_t pgtable;
int version;
 };
@@ -694,8 +695,7 @@ static int exynos_iommu_attach_device(struct iommu_domain 
*domain,
if (!has_sysmmu(dev))
return -ENODEV;
 
-   data = dev_get_drvdata(owner-sysmmu);
-   if (data) {
+   list_for_each_entry(data, owner-clients, owner_node) {
ret = __sysmmu_enable(data, pagetable, domain);
if (ret = 0) {
data-master = dev;
@@ -723,7 +723,7 @@ static void exynos_iommu_detach_device(struct iommu_domain 
*domain,
 {
struct exynos_iommu_domain *priv = domain-priv;
phys_addr_t pagetable = virt_to_phys(priv-pgtable);
-   struct sysmmu_drvdata *data;
+   struct sysmmu_drvdata *data, *next;
unsigned long flags;
int found = 0;
 
@@ -731,14 +731,13 @@ static void exynos_iommu_detach_device(struct 
iommu_domain *domain,
return;
 
spin_lock_irqsave(priv-lock, flags);
-   list_for_each_entry(data, priv-clients, domain_node) {
+   list_for_each_entry_safe(data, next, priv-clients, domain_node) {
if (data-master == dev) {
if (__sysmmu_disable(data)) {
data-master = NULL;
list_del_init(data-domain_node);
}
found = true;
-   break;
}
}
spin_unlock_irqrestore(priv-lock, flags);
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 11/18] iommu: exynos: remove useless device_add/remove callbacks

2014-09-16 Thread Marek Szyprowski
The driver doesn't need to do anything important in device add/remove
callbacks, because initialization will be done from device-tree specific
callbacks added later. IOMMU groups created by current code were never
used.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 28 
 1 file changed, 28 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index b271348a4ec1..1b3f00726cd4 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -1055,32 +1055,6 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct 
iommu_domain *domain,
return phys;
 }
 
-static int exynos_iommu_add_device(struct device *dev)
-{
-   struct iommu_group *group;
-   int ret;
-
-   group = iommu_group_get(dev);
-
-   if (!group) {
-   group = iommu_group_alloc();
-   if (IS_ERR(group)) {
-   dev_err(dev, Failed to allocate IOMMU group\n);
-   return PTR_ERR(group);
-   }
-   }
-
-   ret = iommu_group_add_device(group, dev);
-   iommu_group_put(group);
-
-   return ret;
-}
-
-static void exynos_iommu_remove_device(struct device *dev)
-{
-   iommu_group_remove_device(dev);
-}
-
 static const struct iommu_ops exynos_iommu_ops = {
.domain_init = exynos_iommu_domain_init,
.domain_destroy = exynos_iommu_domain_destroy,
@@ -1089,8 +1063,6 @@ static const struct iommu_ops exynos_iommu_ops = {
.map = exynos_iommu_map,
.unmap = exynos_iommu_unmap,
.iova_to_phys = exynos_iommu_iova_to_phys,
-   .add_device = exynos_iommu_add_device,
-   .remove_device = exynos_iommu_remove_device,
.pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE,
 };
 
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 17/18] iommu: exynos: init from dt-specific callback instead of initcall

2014-09-16 Thread Marek Szyprowski
This patch introduces IOMMU_OF_DECLARE-based initialization to the
driver, which replaces subsys_initcall-based procedure.
exynos_iommu_of_setup ensures that each sysmmu controller is probed
before its master device. 

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 32 +++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 5eb999d7653a..0d304c62956e 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -13,16 +13,21 @@
 #endif
 
 #include linux/clk.h
+#include linux/dma-mapping.h
 #include linux/err.h
 #include linux/io.h
 #include linux/iommu.h
 #include linux/interrupt.h
 #include linux/list.h
+#include linux/of.h
+#include linux/of_iommu.h
+#include linux/of_platform.h
 #include linux/platform_device.h
 #include linux/pm_runtime.h
 #include linux/slab.h
 
 #include asm/cacheflush.h
+#include asm/dma-iommu.h
 #include asm/pgtable.h
 
 typedef u32 sysmmu_iova_t;
@@ -1083,6 +1088,8 @@ static const struct iommu_ops exynos_iommu_ops = {
.pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE,
 };
 
+static int init_done;
+
 static int __init exynos_iommu_init(void)
 {
int ret;
@@ -1115,6 +1122,8 @@ static int __init exynos_iommu_init(void)
goto err_set_iommu;
}
 
+   init_done = true;
+
return 0;
 err_set_iommu:
kmem_cache_free(lv2table_kmem_cache, zero_lv2_table);
@@ -1124,4 +1133,25 @@ err_reg_driver:
kmem_cache_destroy(lv2table_kmem_cache);
return ret;
 }
-subsys_initcall(exynos_iommu_init);
+
+static struct iommu_data exynos_of_data = {
+   .ops = exynos_iommu_ops,
+};
+
+static int __init exynos_iommu_of_setup(struct device_node *np)
+{
+   struct platform_device *pdev;
+
+   if (!init_done)
+   exynos_iommu_init();
+
+   pdev = of_platform_device_create(np, NULL, platform_bus_type.dev_root);
+   if (IS_ERR(pdev))
+   return PTR_ERR(pdev);
+
+   of_iommu_set_data(np, exynos_of_data);
+   return 0;
+}
+
+IOMMU_OF_DECLARE(exynos_iommu_of, samsung,exynos-sysmmu,
+exynos_iommu_of_setup);
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 16/18] iommu: exynos: remove excessive includes and sort others alphabetically

2014-09-16 Thread Marek Szyprowski
Removed following unused includes: linux/mm.h, linux/errno.h,
linux/memblock.h and linux/export.h.

Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
---
 drivers/iommu/exynos-iommu.c | 14 +-
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index a75b06365f97..5eb999d7653a 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -12,19 +12,15 @@
 #define DEBUG
 #endif
 
-#include linux/io.h
-#include linux/interrupt.h
-#include linux/platform_device.h
-#include linux/slab.h
-#include linux/pm_runtime.h
 #include linux/clk.h
 #include linux/err.h
-#include linux/mm.h
+#include linux/io.h
 #include linux/iommu.h
-#include linux/errno.h
+#include linux/interrupt.h
 #include linux/list.h
-#include linux/memblock.h
-#include linux/export.h
+#include linux/platform_device.h
+#include linux/pm_runtime.h
+#include linux/slab.h
 
 #include asm/cacheflush.h
 #include asm/pgtable.h
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


  1   2   3   4   5   6   7   8   9   >