2016-03-17 22:02:35

by Sinan Kaya

[permalink] [raw]
Subject: [PATCH 1/3] crypto: marvell/cesa - replace dma_to_phys with dma_map_single

Getting ready to remove dma_to_phys API. Drivers should not be
using this API for DMA operations. Instead, they should go
through the dma_map or dma_alloc APIs.

Signed-off-by: Sinan Kaya <[email protected]>
---
drivers/crypto/marvell/cesa.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c
index c0656e7..52ddfa4 100644
--- a/drivers/crypto/marvell/cesa.c
+++ b/drivers/crypto/marvell/cesa.c
@@ -350,8 +350,8 @@ static int mv_cesa_get_sram(struct platform_device *pdev, int idx)
if (IS_ERR(engine->sram))
return PTR_ERR(engine->sram);

- engine->sram_dma = phys_to_dma(cesa->dev,
- (phys_addr_t)res->start);
+ engine->sram_dma = dma_map_single(cesa->dev, engine->sram,
+ DMA_TO_DEVICE);

return 0;
}
--
1.8.2.1


2016-03-17 22:03:13

by Sinan Kaya

[permalink] [raw]
Subject: [PATCH 2/3] swiotlb: prefix dma_to_phys and phys_to_dma functions

Prefixing dma_to_phys and phys_to_dma API with swiotlb so that
they are no longer part of the DMA API. These APIs do not exist
on all architectures and breaks compatibility.

In preparation for the clean up, also make the ARCH implementation
known by defining swiotlb_phys_do_dma and swiotlb_dma_to_phys.

Signed-off-by: Sinan Kaya <[email protected]>
---
arch/arm/include/asm/dma-mapping.h | 8 ++-
arch/arm64/include/asm/dma-mapping.h | 9 ++-
arch/arm64/mm/dma-mapping.c | 75 ++++++++++++++--------
arch/ia64/include/asm/dma-mapping.h | 8 ++-
arch/mips/cavium-octeon/dma-octeon.c | 8 +--
.../include/asm/mach-cavium-octeon/dma-coherence.h | 7 +-
arch/mips/include/asm/mach-generic/dma-coherence.h | 8 ++-
.../include/asm/mach-loongson64/dma-coherence.h | 14 ++--
arch/mips/loongson64/common/dma-swiotlb.c | 4 +-
arch/powerpc/include/asm/dma-mapping.h | 8 ++-
arch/tile/include/asm/dma-mapping.h | 8 ++-
arch/unicore32/include/asm/dma-mapping.h | 8 ++-
arch/x86/include/asm/dma-mapping.h | 15 +++--
arch/x86/kernel/pci-swiotlb.c | 2 +-
arch/x86/pci/sta2x11-fixup.c | 10 +--
arch/xtensa/include/asm/dma-mapping.h | 8 ++-
lib/swiotlb.c | 28 ++++----
17 files changed, 150 insertions(+), 78 deletions(-)

diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 6ad1ced..e176689 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -129,17 +129,21 @@ static inline bool is_device_dma_coherent(struct device *dev)
return dev->archdata.dma_coherent;
}

-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev,
+ phys_addr_t paddr)
{
unsigned int offset = paddr & ~PAGE_MASK;
return pfn_to_dma(dev, __phys_to_pfn(paddr)) + offset;
}
+#define swiotlb_phys_to_dma swiotlb_phys_to_dma

-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr)
+static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev,
+ dma_addr_t dev_addr)
{
unsigned int offset = dev_addr & ~PAGE_MASK;
return __pfn_to_phys(dma_to_pfn(dev, dev_addr)) + offset;
}
+#define swiotlb_dma_to_phys swiotlb_dma_to_phys

static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
{
diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
index ba437f0..39f21e8 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -64,15 +64,19 @@ static inline bool is_device_dma_coherent(struct device *dev)
return dev->archdata.dma_coherent;
}

-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev,
+ phys_addr_t paddr)
{
return (dma_addr_t)paddr;
}
+#define swiotlb_phys_to_dma swiotlb_phys_to_dma

-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr)
+static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev,
+ dma_addr_t dev_addr)
{
return (phys_addr_t)dev_addr;
}
+#define swiotlb_dma_to_phys swiotlb_dma_to_phys

static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
{
@@ -88,3 +92,4 @@ static inline void dma_mark_clean(void *addr, size_t size)

#endif /* __KERNEL__ */
#endif /* __ASM_DMA_MAPPING_H */
+
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index a6e757c..ada00c3 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -107,7 +107,7 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size,
if (!page)
return NULL;

- *dma_handle = phys_to_dma(dev, page_to_phys(page));
+ *dma_handle = swiotlb_phys_to_dma(dev, page_to_phys(page));
addr = page_address(page);
memset(addr, 0, size);
return addr;
@@ -121,7 +121,7 @@ static void __dma_free_coherent(struct device *dev, size_t size,
struct dma_attrs *attrs)
{
bool freed;
- phys_addr_t paddr = dma_to_phys(dev, dma_handle);
+ phys_addr_t paddr = swiotlb_dma_to_phys(dev, dma_handle);

if (dev == NULL) {
WARN_ONCE(1, "Use an actual device structure for DMA allocation\n");
@@ -151,7 +151,8 @@ static void *__dma_alloc(struct device *dev, size_t size,
void *addr = __alloc_from_pool(size, &page, flags);

if (addr)
- *dma_handle = phys_to_dma(dev, page_to_phys(page));
+ *dma_handle = swiotlb_phys_to_dma(dev,
+ page_to_phys(page));

return addr;
}
@@ -187,7 +188,7 @@ static void __dma_free(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
struct dma_attrs *attrs)
{
- void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle));
+ void *swiotlb_addr = phys_to_virt(swiotlb_dma_to_phys(dev, dma_handle));

size = PAGE_ALIGN(size);

@@ -208,7 +209,8 @@ static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,

dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs);
if (!is_device_dma_coherent(dev))
- __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
+ __dma_map_area(phys_to_virt(swiotlb_dma_to_phys(dev, dev_addr)),
+ size, dir);

return dev_addr;
}
@@ -218,8 +220,11 @@ static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir,
struct dma_attrs *attrs)
{
- if (!is_device_dma_coherent(dev))
- __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
+ if (!is_device_dma_coherent(dev)) {
+ phys_addr_t phys = swiotlb_dma_to_phys(dev, dev_addr);
+
+ __dma_unmap_area(phys_to_virt(phys), size, dir);
+ }
swiotlb_unmap_page(dev, dev_addr, size, dir, attrs);
}

@@ -232,9 +237,12 @@ static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl,

ret = swiotlb_map_sg_attrs(dev, sgl, nelems, dir, attrs);
if (!is_device_dma_coherent(dev))
- for_each_sg(sgl, sg, ret, i)
- __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
- sg->length, dir);
+ for_each_sg(sgl, sg, ret, i) {
+ dma_addr_t dma = sg->dma_address;
+ phys_addr_t phys = swiotlb_dma_to_phys(dev, dma);
+
+ __dma_map_area(phys_to_virt(phys), sg->length, dir);
+ }

return ret;
}
@@ -248,9 +256,12 @@ static void __swiotlb_unmap_sg_attrs(struct device *dev,
int i;

if (!is_device_dma_coherent(dev))
- for_each_sg(sgl, sg, nelems, i)
- __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
- sg->length, dir);
+ for_each_sg(sgl, sg, nelems, i) {
+ dma_addr_t dma = sg->dma_address;
+ phys_addr_t phys = swiotlb_dma_to_phys(dev, dma);
+
+ __dma_unmap_area(phys_to_virt(phys), sg->length, dir);
+ }
swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs);
}

@@ -258,8 +269,11 @@ static void __swiotlb_sync_single_for_cpu(struct device *dev,
dma_addr_t dev_addr, size_t size,
enum dma_data_direction dir)
{
- if (!is_device_dma_coherent(dev))
- __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
+ if (!is_device_dma_coherent(dev)) {
+ phys_addr_t phys = swiotlb_dma_to_phys(dev, dev_addr);
+
+ __dma_unmap_area(phys_to_virt(phys), size, dir);
+ }
swiotlb_sync_single_for_cpu(dev, dev_addr, size, dir);
}

@@ -269,7 +283,8 @@ static void __swiotlb_sync_single_for_device(struct device *dev,
{
swiotlb_sync_single_for_device(dev, dev_addr, size, dir);
if (!is_device_dma_coherent(dev))
- __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
+ __dma_map_area(phys_to_virt(swiotlb_dma_to_phys(dev, dev_addr)),
+ size, dir);
}

static void __swiotlb_sync_sg_for_cpu(struct device *dev,
@@ -280,9 +295,12 @@ static void __swiotlb_sync_sg_for_cpu(struct device *dev,
int i;

if (!is_device_dma_coherent(dev))
- for_each_sg(sgl, sg, nelems, i)
- __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
- sg->length, dir);
+ for_each_sg(sgl, sg, nelems, i) {
+ dma_addr_t dma = sg->dma_address;
+ phys_addr_t phys = swiotlb_dma_to_phys(dev, dma);
+
+ __dma_unmap_area(phys_to_virt(phys), sg->length, dir);
+ }
swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir);
}

@@ -295,9 +313,12 @@ static void __swiotlb_sync_sg_for_device(struct device *dev,

swiotlb_sync_sg_for_device(dev, sgl, nelems, dir);
if (!is_device_dma_coherent(dev))
- for_each_sg(sgl, sg, nelems, i)
- __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
- sg->length, dir);
+ for_each_sg(sgl, sg, nelems, i) {
+ dma_addr_t dma = sg->dma_address;
+ phys_addr_t phys = swiotlb_dma_to_phys(dev, dma);
+
+ __dma_map_area(phys_to_virt(phys), sg->length, dir);
+ }
}

static int __swiotlb_mmap(struct device *dev,
@@ -309,7 +330,7 @@ static int __swiotlb_mmap(struct device *dev,
unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >>
PAGE_SHIFT;
unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
- unsigned long pfn = dma_to_phys(dev, dma_addr) >> PAGE_SHIFT;
+ unsigned long pfn = swiotlb_dma_to_phys(dev, dma_addr) >> PAGE_SHIFT;
unsigned long off = vma->vm_pgoff;

vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot,
@@ -334,9 +355,11 @@ static int __swiotlb_get_sgtable(struct device *dev, struct sg_table *sgt,
{
int ret = sg_alloc_table(sgt, 1, GFP_KERNEL);

- if (!ret)
- sg_set_page(sgt->sgl, phys_to_page(dma_to_phys(dev, handle)),
- PAGE_ALIGN(size), 0);
+ if (!ret) {
+ phys_addr_t phys = swiotlb_dma_to_phys(dev, handle);
+
+ sg_set_page(sgt->sgl, phys_to_page(phys), PAGE_ALIGN(size), 0);
+ }

return ret;
}
diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h
index d472805..a8736b9 100644
--- a/arch/ia64/include/asm/dma-mapping.h
+++ b/arch/ia64/include/asm/dma-mapping.h
@@ -33,15 +33,19 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
return addr + size - 1 <= *dev->dma_mask;
}

-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev,
+ phys_addr_t paddr)
{
return paddr;
}
+#define swiotlb_phys_to_dma swiotlb_phys_to_dma

-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev,
+ dma_addr_t daddr)
{
return daddr;
}
+#define swiotlb_dma_to_phys swiotlb_dma_to_phys

static inline void
dma_cache_sync (struct device *dev, void *vaddr, size_t size,
diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c
index 2cd45f5..9ea7e9b 100644
--- a/arch/mips/cavium-octeon/dma-octeon.c
+++ b/arch/mips/cavium-octeon/dma-octeon.c
@@ -210,7 +210,7 @@ struct octeon_dma_map_ops {
phys_addr_t (*dma_to_phys)(struct device *dev, dma_addr_t daddr);
};

-dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+dma_addr_t swiotlb_phys_to_dma(struct device *dev, phys_addr_t paddr)
{
struct octeon_dma_map_ops *ops = container_of(get_dma_ops(dev),
struct octeon_dma_map_ops,
@@ -218,9 +218,9 @@ dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)

return ops->phys_to_dma(dev, paddr);
}
-EXPORT_SYMBOL(phys_to_dma);
+EXPORT_SYMBOL(swiotlb_phys_to_dma);

-phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+phys_addr_t swiotlb_dma_to_phys(struct device *dev, dma_addr_t daddr)
{
struct octeon_dma_map_ops *ops = container_of(get_dma_ops(dev),
struct octeon_dma_map_ops,
@@ -228,7 +228,7 @@ phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)

return ops->dma_to_phys(dev, daddr);
}
-EXPORT_SYMBOL(dma_to_phys);
+EXPORT_SYMBOL(swiotlb_dma_to_phys);

static struct octeon_dma_map_ops octeon_linear_dma_map_ops = {
.dma_map_ops = {
diff --git a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
index 460042e..5f0f13a 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
@@ -61,8 +61,11 @@ static inline void plat_post_dma_flush(struct device *dev)
{
}

-dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
-phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
+dma_addr_t swiotlb_phys_to_dma(struct device *dev, phys_addr_t paddr);
+#define swiotlb_phys_to_dma swiotlb_phys_to_dma
+
+phys_addr_t swiotlb_dma_to_phys(struct device *dev, dma_addr_t daddr);
+#define swiotlb_dma_to_phys swiotlb_dma_to_phys

struct dma_map_ops;
extern struct dma_map_ops *octeon_pci_dma_map_ops;
diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h
index 0f8a354..54fde22 100644
--- a/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ b/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -59,15 +59,19 @@ static inline void plat_post_dma_flush(struct device *dev)
#endif

#ifdef CONFIG_SWIOTLB
-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev,
+ phys_addr_t paddr)
{
return paddr;
}
+#define swiotlb_phys_to_dma swiotlb_phys_to_dma

-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev,
+ dma_addr_t daddr)
{
return daddr;
}
+#define swiotlb_dma_to_phys swiotlb_dma_to_phys
#endif

#endif /* __ASM_MACH_GENERIC_DMA_COHERENCE_H */
diff --git a/arch/mips/include/asm/mach-loongson64/dma-coherence.h b/arch/mips/include/asm/mach-loongson64/dma-coherence.h
index 1602a9e..26fe763 100644
--- a/arch/mips/include/asm/mach-loongson64/dma-coherence.h
+++ b/arch/mips/include/asm/mach-loongson64/dma-coherence.h
@@ -17,13 +17,17 @@

struct device;

-extern dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
-extern phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
+extern dma_addr_t swiotlb_phys_to_dma(struct device *dev, phys_addr_t paddr);
+#define swiotlb_phys_to_dma swiotlb_phys_to_dma
+
+extern phys_addr_t swiotlb_dma_to_phys(struct device *dev, dma_addr_t daddr);
+#define swiotlb_dma_to_phys swiotlb_dma_to_phys
+
static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
size_t size)
{
#ifdef CONFIG_CPU_LOONGSON3
- return phys_to_dma(dev, virt_to_phys(addr));
+ return swiotlb_phys_to_dma(dev, virt_to_phys(addr));
#else
return virt_to_phys(addr) | 0x80000000;
#endif
@@ -33,7 +37,7 @@ static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
struct page *page)
{
#ifdef CONFIG_CPU_LOONGSON3
- return phys_to_dma(dev, page_to_phys(page));
+ return swiotlb_phys_to_dma(dev, page_to_phys(page));
#else
return page_to_phys(page) | 0x80000000;
#endif
@@ -43,7 +47,7 @@ static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
dma_addr_t dma_addr)
{
#if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT)
- return dma_to_phys(dev, dma_addr);
+ return swiotlb_dma_to_phys(dev, dma_addr);
#elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff);
#else
diff --git a/arch/mips/loongson64/common/dma-swiotlb.c b/arch/mips/loongson64/common/dma-swiotlb.c
index 4ffa6fc..88ef4cf 100644
--- a/arch/mips/loongson64/common/dma-swiotlb.c
+++ b/arch/mips/loongson64/common/dma-swiotlb.c
@@ -98,7 +98,7 @@ static int loongson_dma_set_mask(struct device *dev, u64 mask)
return 0;
}

-dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+dma_addr_t swiotlb_phys_to_dma(struct device *dev, phys_addr_t paddr)
{
long nid;
#ifdef CONFIG_PHYS48_TO_HT40
@@ -110,7 +110,7 @@ dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
return paddr;
}

-phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+phys_addr_t swiotlb_dma_to_phys(struct device *dev, dma_addr_t daddr)
{
long nid;
#ifdef CONFIG_PHYS48_TO_HT40
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 77816ac..3a9d6f2 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -143,15 +143,19 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
return addr + size - 1 <= *dev->dma_mask;
}

-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev,
+ phys_addr_t paddr)
{
return paddr + get_dma_offset(dev);
}
+#define swiotlb_phys_to_dma swiotlb_phys_to_dma

-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev,
+ dma_addr_t daddr)
{
return daddr - get_dma_offset(dev);
}
+#define swiotlb_dma_to_phys swiotlb_dma_to_phys

#define ARCH_HAS_DMA_MMAP_COHERENT

diff --git a/arch/tile/include/asm/dma-mapping.h b/arch/tile/include/asm/dma-mapping.h
index 01ceb4a..87c205a 100644
--- a/arch/tile/include/asm/dma-mapping.h
+++ b/arch/tile/include/asm/dma-mapping.h
@@ -47,15 +47,19 @@ static inline void set_dma_offset(struct device *dev, dma_addr_t off)
dev->archdata.dma_offset = off;
}

-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev,
+ phys_addr_t paddr)
{
return paddr;
}
+#define swiotlb_phys_to_dma swiotlb_phys_to_dma

-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev,
+ dma_addr_t daddr)
{
return daddr;
}
+#define swiotlb_dma_to_phys swiotlb_dma_to_phys

static inline void dma_mark_clean(void *addr, size_t size) {}

diff --git a/arch/unicore32/include/asm/dma-mapping.h b/arch/unicore32/include/asm/dma-mapping.h
index 4749854..762cdd8 100644
--- a/arch/unicore32/include/asm/dma-mapping.h
+++ b/arch/unicore32/include/asm/dma-mapping.h
@@ -36,15 +36,19 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
return 1;
}

-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev,
+ phys_addr_t paddr)
{
return paddr;
}
+#define swiotlb_phys_to_dma swiotlb_phys_to_dma

-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev,
+ dma_addr_t daddr)
{
return daddr;
}
+#define swiotlb_dma_to_phys swiotlb_dma_to_phys

static inline void dma_mark_clean(void *addr, size_t size) {}

diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index 3a27b93..be8b76e 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -56,8 +56,11 @@ extern void dma_generic_free_coherent(struct device *dev, size_t size,

#ifdef CONFIG_X86_DMA_REMAP /* Platform code defines bridge-specific code */
extern bool dma_capable(struct device *dev, dma_addr_t addr, size_t size);
-extern dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
-extern phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
+extern dma_addr_t swiotlb_phys_to_dma(struct device *dev, phys_addr_t paddr);
+#define swiotlb_phys_to_dma swiotlb_phys_to_dma
+
+extern phys_addr_t swiotlb_dma_to_phys(struct device *dev, dma_addr_t daddr);
+#define swiotlb_dma_to_phys swiotlb_dma_to_phys
#else

static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
@@ -68,15 +71,19 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
return addr + size - 1 <= *dev->dma_mask;
}

-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev,
+ phys_addr_t paddr)
{
return paddr;
}
+#define swiotlb_phys_to_dma swiotlb_phys_to_dma

-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev,
+ dma_addr_t daddr)
{
return daddr;
}
+#define swiotlb_dma_to_phys swiotlb_dma_to_phys
#endif /* CONFIG_X86_DMA_REMAP */

static inline void
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index 7c577a1..9333fbd 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -39,7 +39,7 @@ void x86_swiotlb_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_addr,
struct dma_attrs *attrs)
{
- if (is_swiotlb_buffer(dma_to_phys(dev, dma_addr)))
+ if (is_swiotlb_buffer(swiotlb_dma_to_phys(dev, dma_addr)))
swiotlb_free_coherent(dev, size, vaddr, dma_addr);
else
dma_generic_free_coherent(dev, size, vaddr, dma_addr, attrs);
diff --git a/arch/x86/pci/sta2x11-fixup.c b/arch/x86/pci/sta2x11-fixup.c
index 5ceda85..6df3eb4 100644
--- a/arch/x86/pci/sta2x11-fixup.c
+++ b/arch/x86/pci/sta2x11-fixup.c
@@ -241,11 +241,12 @@ bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
}

/**
- * phys_to_dma - Return the DMA AMBA address used for this STA2x11 device
+ * swiotlb_phys_to_dma - Return the DMA AMBA address used for this
+ * STA2x11 device
* @dev: device for a PCI device
* @paddr: Physical address
*/
-dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+dma_addr_t swiotlb_phys_to_dma(struct device *dev, phys_addr_t paddr)
{
if (dev->archdata.dma_ops != &sta2x11_dma_ops)
return paddr;
@@ -253,11 +254,12 @@ dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
}

/**
- * dma_to_phys - Return the physical address used for this STA2x11 DMA address
+ * swiotlb_dma_to_phys - Return the physical address used for this
+ * STA2x11 DMA address
* @dev: device for a PCI device
* @daddr: STA2x11 AMBA DMA address
*/
-phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+phys_addr_t swiotlb_dma_to_phys(struct device *dev, dma_addr_t daddr)
{
if (dev->archdata.dma_ops != &sta2x11_dma_ops)
return daddr;
diff --git a/arch/xtensa/include/asm/dma-mapping.h b/arch/xtensa/include/asm/dma-mapping.h
index 3fc1170..b0d725d 100644
--- a/arch/xtensa/include/asm/dma-mapping.h
+++ b/arch/xtensa/include/asm/dma-mapping.h
@@ -31,14 +31,18 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)
void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction direction);

-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev,
+ phys_addr_t paddr)
{
return (dma_addr_t)paddr;
}
+#define swiotlb_phys_to_dma swiotlb_phys_to_dma

-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev,
+ dma_addr_t daddr)
{
return (phys_addr_t)daddr;
}
+#define swiotlb_dma_to_phys swiotlb_dma_to_phys

#endif /* _XTENSA_DMA_MAPPING_H */
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 76f29ec..5aadeca 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -135,7 +135,7 @@ unsigned long swiotlb_size_or_default(void)
static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
volatile void *address)
{
- return phys_to_dma(hwdev, virt_to_phys(address));
+ return swiotlb_phys_to_dma(hwdev, virt_to_phys(address));
}

static bool no_iotlb_memory;
@@ -541,7 +541,7 @@ static phys_addr_t
map_single(struct device *hwdev, phys_addr_t phys, size_t size,
enum dma_data_direction dir)
{
- dma_addr_t start_dma_addr = phys_to_dma(hwdev, io_tlb_start);
+ dma_addr_t start_dma_addr = swiotlb_phys_to_dma(hwdev, io_tlb_start);

return swiotlb_tbl_map_single(hwdev, start_dma_addr, phys, size, dir);
}
@@ -659,7 +659,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
goto err_warn;

ret = phys_to_virt(paddr);
- dev_addr = phys_to_dma(hwdev, paddr);
+ dev_addr = swiotlb_phys_to_dma(hwdev, paddr);

/* Confirm address can be DMA'd by device */
if (dev_addr + size - 1 > dma_mask) {
@@ -692,7 +692,7 @@ void
swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
dma_addr_t dev_addr)
{
- phys_addr_t paddr = dma_to_phys(hwdev, dev_addr);
+ phys_addr_t paddr = swiotlb_dma_to_phys(hwdev, dev_addr);

WARN_ON(irqs_disabled());
if (!is_swiotlb_buffer(paddr))
@@ -741,7 +741,7 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
struct dma_attrs *attrs)
{
phys_addr_t map, phys = page_to_phys(page) + offset;
- dma_addr_t dev_addr = phys_to_dma(dev, phys);
+ dma_addr_t dev_addr = swiotlb_phys_to_dma(dev, phys);

BUG_ON(dir == DMA_NONE);
/*
@@ -758,15 +758,15 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
map = map_single(dev, phys, size, dir);
if (map == SWIOTLB_MAP_ERROR) {
swiotlb_full(dev, size, dir, 1);
- return phys_to_dma(dev, io_tlb_overflow_buffer);
+ return swiotlb_phys_to_dma(dev, io_tlb_overflow_buffer);
}

- dev_addr = phys_to_dma(dev, map);
+ dev_addr = swiotlb_phys_to_dma(dev, map);

/* Ensure that the address returned is DMA'ble */
if (!dma_capable(dev, dev_addr, size)) {
swiotlb_tbl_unmap_single(dev, map, size, dir);
- return phys_to_dma(dev, io_tlb_overflow_buffer);
+ return swiotlb_phys_to_dma(dev, io_tlb_overflow_buffer);
}

return dev_addr;
@@ -784,7 +784,7 @@ EXPORT_SYMBOL_GPL(swiotlb_map_page);
static void unmap_single(struct device *hwdev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir)
{
- phys_addr_t paddr = dma_to_phys(hwdev, dev_addr);
+ phys_addr_t paddr = swiotlb_dma_to_phys(hwdev, dev_addr);

BUG_ON(dir == DMA_NONE);

@@ -828,7 +828,7 @@ swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir,
enum dma_sync_target target)
{
- phys_addr_t paddr = dma_to_phys(hwdev, dev_addr);
+ phys_addr_t paddr = swiotlb_dma_to_phys(hwdev, dev_addr);

BUG_ON(dir == DMA_NONE);

@@ -886,7 +886,7 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,

for_each_sg(sgl, sg, nelems, i) {
phys_addr_t paddr = sg_phys(sg);
- dma_addr_t dev_addr = phys_to_dma(hwdev, paddr);
+ dma_addr_t dev_addr = swiotlb_phys_to_dma(hwdev, paddr);

if (swiotlb_force ||
!dma_capable(hwdev, dev_addr, sg->length)) {
@@ -901,7 +901,7 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
sg_dma_len(sgl) = 0;
return 0;
}
- sg->dma_address = phys_to_dma(hwdev, map);
+ sg->dma_address = swiotlb_phys_to_dma(hwdev, map);
} else
sg->dma_address = dev_addr;
sg_dma_len(sg) = sg->length;
@@ -984,7 +984,7 @@ EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
int
swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr)
{
- return (dma_addr == phys_to_dma(hwdev, io_tlb_overflow_buffer));
+ return (dma_addr == swiotlb_phys_to_dma(hwdev, io_tlb_overflow_buffer));
}
EXPORT_SYMBOL(swiotlb_dma_mapping_error);

@@ -997,6 +997,6 @@ EXPORT_SYMBOL(swiotlb_dma_mapping_error);
int
swiotlb_dma_supported(struct device *hwdev, u64 mask)
{
- return phys_to_dma(hwdev, io_tlb_end - 1) <= mask;
+ return swiotlb_phys_to_dma(hwdev, io_tlb_end - 1) <= mask;
}
EXPORT_SYMBOL(swiotlb_dma_supported);
--
1.8.2.1

2016-03-17 22:03:27

by Sinan Kaya

[permalink] [raw]
Subject: [PATCH 3/3] dma-mapping: move swiotlb dma-phys functions to common header

Moving the default implementation of swiotlb_dma_to_phys and
swiotlb_phys_to_dma functions to dma-mapping.h so that we can get
rid of the duplicate code in multiple ARCH.

Signed-off-by: Sinan Kaya <[email protected]>
---
arch/arm64/include/asm/dma-mapping.h | 14 --------------
arch/ia64/include/asm/dma-mapping.h | 14 --------------
arch/mips/include/asm/mach-generic/dma-coherence.h | 16 ----------------
arch/tile/include/asm/dma-mapping.h | 14 --------------
arch/unicore32/include/asm/dma-mapping.h | 14 --------------
arch/x86/include/asm/dma-mapping.h | 13 -------------
arch/xtensa/include/asm/dma-mapping.h | 14 --------------
include/linux/dma-mapping.h | 14 ++++++++++++++
8 files changed, 14 insertions(+), 99 deletions(-)

diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
index 39f21e8..5654357 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -64,20 +64,6 @@ static inline bool is_device_dma_coherent(struct device *dev)
return dev->archdata.dma_coherent;
}

-static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev,
- phys_addr_t paddr)
-{
- return (dma_addr_t)paddr;
-}
-#define swiotlb_phys_to_dma swiotlb_phys_to_dma
-
-static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev,
- dma_addr_t dev_addr)
-{
- return (phys_addr_t)dev_addr;
-}
-#define swiotlb_dma_to_phys swiotlb_dma_to_phys
-
static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
{
if (!dev->dma_mask)
diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h
index a8736b9..e6dd1f7 100644
--- a/arch/ia64/include/asm/dma-mapping.h
+++ b/arch/ia64/include/asm/dma-mapping.h
@@ -33,20 +33,6 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
return addr + size - 1 <= *dev->dma_mask;
}

-static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev,
- phys_addr_t paddr)
-{
- return paddr;
-}
-#define swiotlb_phys_to_dma swiotlb_phys_to_dma
-
-static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev,
- dma_addr_t daddr)
-{
- return daddr;
-}
-#define swiotlb_dma_to_phys swiotlb_dma_to_phys
-
static inline void
dma_cache_sync (struct device *dev, void *vaddr, size_t size,
enum dma_data_direction dir)
diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h
index 54fde22..7bb5de0 100644
--- a/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ b/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -58,20 +58,4 @@ static inline void plat_post_dma_flush(struct device *dev)
}
#endif

-#ifdef CONFIG_SWIOTLB
-static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev,
- phys_addr_t paddr)
-{
- return paddr;
-}
-#define swiotlb_phys_to_dma swiotlb_phys_to_dma
-
-static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev,
- dma_addr_t daddr)
-{
- return daddr;
-}
-#define swiotlb_dma_to_phys swiotlb_dma_to_phys
-#endif
-
#endif /* __ASM_MACH_GENERIC_DMA_COHERENCE_H */
diff --git a/arch/tile/include/asm/dma-mapping.h b/arch/tile/include/asm/dma-mapping.h
index 87c205a..c9cc14e 100644
--- a/arch/tile/include/asm/dma-mapping.h
+++ b/arch/tile/include/asm/dma-mapping.h
@@ -47,20 +47,6 @@ static inline void set_dma_offset(struct device *dev, dma_addr_t off)
dev->archdata.dma_offset = off;
}

-static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev,
- phys_addr_t paddr)
-{
- return paddr;
-}
-#define swiotlb_phys_to_dma swiotlb_phys_to_dma
-
-static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev,
- dma_addr_t daddr)
-{
- return daddr;
-}
-#define swiotlb_dma_to_phys swiotlb_dma_to_phys
-
static inline void dma_mark_clean(void *addr, size_t size) {}

static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
diff --git a/arch/unicore32/include/asm/dma-mapping.h b/arch/unicore32/include/asm/dma-mapping.h
index 762cdd8..c629aa5 100644
--- a/arch/unicore32/include/asm/dma-mapping.h
+++ b/arch/unicore32/include/asm/dma-mapping.h
@@ -36,20 +36,6 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
return 1;
}

-static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev,
- phys_addr_t paddr)
-{
- return paddr;
-}
-#define swiotlb_phys_to_dma swiotlb_phys_to_dma
-
-static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev,
- dma_addr_t daddr)
-{
- return daddr;
-}
-#define swiotlb_dma_to_phys swiotlb_dma_to_phys
-
static inline void dma_mark_clean(void *addr, size_t size) {}

static inline void dma_cache_sync(struct device *dev, void *vaddr,
diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index be8b76e..fd5c7de 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -71,19 +71,6 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
return addr + size - 1 <= *dev->dma_mask;
}

-static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev,
- phys_addr_t paddr)
-{
- return paddr;
-}
-#define swiotlb_phys_to_dma swiotlb_phys_to_dma
-
-static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev,
- dma_addr_t daddr)
-{
- return daddr;
-}
-#define swiotlb_dma_to_phys swiotlb_dma_to_phys
#endif /* CONFIG_X86_DMA_REMAP */

static inline void
diff --git a/arch/xtensa/include/asm/dma-mapping.h b/arch/xtensa/include/asm/dma-mapping.h
index b0d725d..4e6ff4d 100644
--- a/arch/xtensa/include/asm/dma-mapping.h
+++ b/arch/xtensa/include/asm/dma-mapping.h
@@ -31,18 +31,4 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)
void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction direction);

-static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev,
- phys_addr_t paddr)
-{
- return (dma_addr_t)paddr;
-}
-#define swiotlb_phys_to_dma swiotlb_phys_to_dma
-
-static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev,
- dma_addr_t daddr)
-{
- return (phys_addr_t)daddr;
-}
-#define swiotlb_dma_to_phys swiotlb_dma_to_phys
-
#endif /* _XTENSA_DMA_MAPPING_H */
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 728ef07..871d620 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -683,4 +683,18 @@ static inline int dma_mmap_writecombine(struct device *dev,
#define dma_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
#endif

+#ifndef swiotlb_phys_to_dma
+static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+ return paddr;
+}
+#endif
+
+#ifndef swiotlb_dma_to_phys
+static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+ return daddr;
+}
+#endif
+
#endif
--
1.8.2.1

2016-03-17 22:55:32

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: [PATCH 1/3] crypto: marvell/cesa - replace dma_to_phys with dma_map_single

On Thu, Mar 17, 2016 at 06:02:15PM -0400, Sinan Kaya wrote:
> Getting ready to remove dma_to_phys API. Drivers should not be
> using this API for DMA operations. Instead, they should go
> through the dma_map or dma_alloc APIs.
>
> Signed-off-by: Sinan Kaya <[email protected]>
> ---
> drivers/crypto/marvell/cesa.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c
> index c0656e7..52ddfa4 100644
> --- a/drivers/crypto/marvell/cesa.c
> +++ b/drivers/crypto/marvell/cesa.c
> @@ -350,8 +350,8 @@ static int mv_cesa_get_sram(struct platform_device *pdev, int idx)
> if (IS_ERR(engine->sram))
> return PTR_ERR(engine->sram);
>
> - engine->sram_dma = phys_to_dma(cesa->dev,
> - (phys_addr_t)res->start);
> + engine->sram_dma = dma_map_single(cesa->dev, engine->sram,
> + DMA_TO_DEVICE);

Documentation/DMA-API.txt

dma_addr_t
dma_map_single(struct device *dev, void *cpu_addr, size_t size,
enum dma_data_direction direction)

Notes: Not all memory regions in a machine can be mapped by this API.
Further, contiguous kernel virtual space may not be contiguous as
physical memory. Since this API does not provide any scatter/gather
capability, it will fail if the user tries to map a non-physically
contiguous piece of memory. For this reason, memory to be mapped by
this API should be obtained from sources which guarantee it to be
physically contiguous (like kmalloc).

Specifically, ioremapped memory will *not* work as you expect with
dma_map_single().

--
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

2016-03-17 23:17:27

by Sinan Kaya

[permalink] [raw]
Subject: Re: [PATCH 1/3] crypto: marvell/cesa - replace dma_to_phys with dma_map_single

On 2016-03-17 18:54, Russell King - ARM Linux wrote:
> On Thu, Mar 17, 2016 at 06:02:15PM -0400, Sinan Kaya wrote:
>> Getting ready to remove dma_to_phys API. Drivers should not be
>> using this API for DMA operations. Instead, they should go
>> through the dma_map or dma_alloc APIs.
>>
>> Signed-off-by: Sinan Kaya <[email protected]>
>> ---
>> drivers/crypto/marvell/cesa.c | 4 ++--
>> 1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/crypto/marvell/cesa.c
>> b/drivers/crypto/marvell/cesa.c
>> index c0656e7..52ddfa4 100644
>> --- a/drivers/crypto/marvell/cesa.c
>> +++ b/drivers/crypto/marvell/cesa.c
>> @@ -350,8 +350,8 @@ static int mv_cesa_get_sram(struct platform_device
>> *pdev, int idx)
>> if (IS_ERR(engine->sram))
>> return PTR_ERR(engine->sram);
>>
>> - engine->sram_dma = phys_to_dma(cesa->dev,
>> - (phys_addr_t)res->start);
>> + engine->sram_dma = dma_map_single(cesa->dev, engine->sram,
>> + DMA_TO_DEVICE);
>
> Documentation/DMA-API.txt
>
> dma_addr_t
> dma_map_single(struct device *dev, void *cpu_addr, size_t size,
> enum dma_data_direction direction)
>
> Notes: Not all memory regions in a machine can be mapped by this API.
> Further, contiguous kernel virtual space may not be contiguous as
> physical memory. Since this API does not provide any scatter/gather
> capability, it will fail if the user tries to map a non-physically
> contiguous piece of memory. For this reason, memory to be mapped by
> this API should be obtained from sources which guarantee it to be
> physically contiguous (like kmalloc).
>
> Specifically, ioremapped memory will *not* work as you expect with
> dma_map_single().


What is the correct way? I don't want to write engine->sram_dma = sram

2016-03-17 23:50:48

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: [PATCH 1/3] crypto: marvell/cesa - replace dma_to_phys with dma_map_single

On Thu, Mar 17, 2016 at 07:17:24PM -0400, [email protected] wrote:
> What is the correct way? I don't want to write engine->sram_dma = sram

Well, what the driver _is_ wanting to do is to go from a CPU physical
address to a device DMA address. phys_to_dma() looks like the correct
thing there to me, but I guess that's just an offset and doesn't take
account of any IOMMU that may be in the way.

If you have an IOMMU, then the whole phys_to_dma() thing is a total
failure as it only does a linear translation, and there are no
interfaces in the kernel to take account of an IOMMU in the way. So,
it needs something designed for the job, implemented and discussed by
the normal methods of proposing a new cross-arch interface for drivers
to use.

What I'm certain of, though, is that the change proposed in this patch
will break current users of this driver: virt_to_page() on an address
returned by ioremap() is completely undefined, and will result in
either a kernel oops, or if not poking at memory which isn't a struct
page, ultimately resulting in something that isn't SRAM being pointed
to by "engine->sram_dma".

--
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

2016-03-18 09:30:42

by Boris Brezillon

[permalink] [raw]
Subject: Re: [PATCH 1/3] crypto: marvell/cesa - replace dma_to_phys with dma_map_single

On Thu, 17 Mar 2016 23:50:20 +0000
Russell King - ARM Linux <[email protected]> wrote:

> On Thu, Mar 17, 2016 at 07:17:24PM -0400, [email protected] wrote:
> > What is the correct way? I don't want to write engine->sram_dma = sram
>
> Well, what the driver _is_ wanting to do is to go from a CPU physical
> address to a device DMA address. phys_to_dma() looks like the correct
> thing there to me, but I guess that's just an offset and doesn't take
> account of any IOMMU that may be in the way.
>
> If you have an IOMMU, then the whole phys_to_dma() thing is a total
> failure as it only does a linear translation, and there are no
> interfaces in the kernel to take account of an IOMMU in the way. So,
> it needs something designed for the job, implemented and discussed by
> the normal methods of proposing a new cross-arch interface for drivers
> to use.
>
> What I'm certain of, though, is that the change proposed in this patch
> will break current users of this driver: virt_to_page() on an address
> returned by ioremap() is completely undefined, and will result in
> either a kernel oops, or if not poking at memory which isn't a struct
> page, ultimately resulting in something that isn't SRAM being pointed
> to by "engine->sram_dma".
>

Or we could just do

engine->sram_dma = res->start;

which is pretty much what the SRAM/genalloc code is doing already.


--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

2016-03-18 11:26:00

by Robin Murphy

[permalink] [raw]
Subject: Re: [PATCH 1/3] crypto: marvell/cesa - replace dma_to_phys with dma_map_single

On 18/03/16 09:30, Boris Brezillon wrote:
> On Thu, 17 Mar 2016 23:50:20 +0000
> Russell King - ARM Linux <[email protected]> wrote:
>
>> On Thu, Mar 17, 2016 at 07:17:24PM -0400, [email protected] wrote:
>>> What is the correct way? I don't want to write engine->sram_dma = sram
>>
>> Well, what the driver _is_ wanting to do is to go from a CPU physical
>> address to a device DMA address. phys_to_dma() looks like the correct
>> thing there to me, but I guess that's just an offset and doesn't take
>> account of any IOMMU that may be in the way.
>>
>> If you have an IOMMU, then the whole phys_to_dma() thing is a total
>> failure as it only does a linear translation, and there are no
>> interfaces in the kernel to take account of an IOMMU in the way. So,
>> it needs something designed for the job, implemented and discussed by
>> the normal methods of proposing a new cross-arch interface for drivers
>> to use.
>>
>> What I'm certain of, though, is that the change proposed in this patch
>> will break current users of this driver: virt_to_page() on an address
>> returned by ioremap() is completely undefined, and will result in
>> either a kernel oops, or if not poking at memory which isn't a struct
>> page, ultimately resulting in something that isn't SRAM being pointed
>> to by "engine->sram_dma".
>>
>
> Or we could just do
>
> engine->sram_dma = res->start;
>
> which is pretty much what the SRAM/genalloc code is doing already.

As Russell points out this is yet another type of "set up a DMA master
to access something other than kernel RAM" - there's already discussion
in progress over how to handle this for dmaengine slaves[1], so
gathering more use-cases might help distil exactly what the design of
not-strictly-DMA-but-so-closely-coupled-it-can't-really-live-anywhere-else
needs to be.

Robin.

[1]:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-March/414422.html

2016-03-18 11:31:59

by Robin Murphy

[permalink] [raw]
Subject: Re: [PATCH 3/3] dma-mapping: move swiotlb dma-phys functions to common header

On 17/03/16 22:02, Sinan Kaya wrote:
> Moving the default implementation of swiotlb_dma_to_phys and
> swiotlb_phys_to_dma functions to dma-mapping.h so that we can get
> rid of the duplicate code in multiple ARCH.
>
> Signed-off-by: Sinan Kaya <[email protected]>
> ---
> arch/arm64/include/asm/dma-mapping.h | 14 --------------
> arch/ia64/include/asm/dma-mapping.h | 14 --------------
> arch/mips/include/asm/mach-generic/dma-coherence.h | 16 ----------------
> arch/tile/include/asm/dma-mapping.h | 14 --------------
> arch/unicore32/include/asm/dma-mapping.h | 14 --------------
> arch/x86/include/asm/dma-mapping.h | 13 -------------
> arch/xtensa/include/asm/dma-mapping.h | 14 --------------
> include/linux/dma-mapping.h | 14 ++++++++++++++
> 8 files changed, 14 insertions(+), 99 deletions(-)

[...]

> diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
> index 728ef07..871d620 100644
> --- a/include/linux/dma-mapping.h
> +++ b/include/linux/dma-mapping.h
> @@ -683,4 +683,18 @@ static inline int dma_mmap_writecombine(struct device *dev,
> #define dma_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
> #endif
>
> +#ifndef swiotlb_phys_to_dma
> +static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev, phys_addr_t paddr)
> +{
> + return paddr;
> +}
> +#endif
> +
> +#ifndef swiotlb_dma_to_phys
> +static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev, dma_addr_t daddr)
> +{
> + return daddr;
> +}
> +#endif
> +
> #endif
>

Could the default definition not be pushed all the way down into
swiotlb.c (or at least swiotlb.h)?

Robin.

2016-03-18 11:32:22

by Boris Brezillon

[permalink] [raw]
Subject: Re: [PATCH 1/3] crypto: marvell/cesa - replace dma_to_phys with dma_map_single

On Fri, 18 Mar 2016 11:25:48 +0000
Robin Murphy <[email protected]> wrote:

> On 18/03/16 09:30, Boris Brezillon wrote:
> > On Thu, 17 Mar 2016 23:50:20 +0000
> > Russell King - ARM Linux <[email protected]> wrote:
> >
> >> On Thu, Mar 17, 2016 at 07:17:24PM -0400, [email protected] wrote:
> >>> What is the correct way? I don't want to write engine->sram_dma = sram
> >>
> >> Well, what the driver _is_ wanting to do is to go from a CPU physical
> >> address to a device DMA address. phys_to_dma() looks like the correct
> >> thing there to me, but I guess that's just an offset and doesn't take
> >> account of any IOMMU that may be in the way.
> >>
> >> If you have an IOMMU, then the whole phys_to_dma() thing is a total
> >> failure as it only does a linear translation, and there are no
> >> interfaces in the kernel to take account of an IOMMU in the way. So,
> >> it needs something designed for the job, implemented and discussed by
> >> the normal methods of proposing a new cross-arch interface for drivers
> >> to use.
> >>
> >> What I'm certain of, though, is that the change proposed in this patch
> >> will break current users of this driver: virt_to_page() on an address
> >> returned by ioremap() is completely undefined, and will result in
> >> either a kernel oops, or if not poking at memory which isn't a struct
> >> page, ultimately resulting in something that isn't SRAM being pointed
> >> to by "engine->sram_dma".
> >>
> >
> > Or we could just do
> >
> > engine->sram_dma = res->start;
> >
> > which is pretty much what the SRAM/genalloc code is doing already.
>
> As Russell points out this is yet another type of "set up a DMA master
> to access something other than kernel RAM" - there's already discussion
> in progress over how to handle this for dmaengine slaves[1], so
> gathering more use-cases might help distil exactly what the design of
> not-strictly-DMA-but-so-closely-coupled-it-can't-really-live-anywhere-else
> needs to be.
>
> Robin.
>
> [1]:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-March/414422.html
>

Hm, interesting, thanks for the pointer.

--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

2016-03-18 12:12:30

by Robin Murphy

[permalink] [raw]
Subject: Re: [PATCH 2/3] swiotlb: prefix dma_to_phys and phys_to_dma functions

On 17/03/16 22:02, Sinan Kaya wrote:
> Prefixing dma_to_phys and phys_to_dma API with swiotlb so that
> they are no longer part of the DMA API. These APIs do not exist
> on all architectures and breaks compatibility.
>
> In preparation for the clean up, also make the ARCH implementation
> known by defining swiotlb_phys_do_dma and swiotlb_dma_to_phys.
>
> Signed-off-by: Sinan Kaya <[email protected]>
> ---
> arch/arm/include/asm/dma-mapping.h | 8 ++-
> arch/arm64/include/asm/dma-mapping.h | 9 ++-
> arch/arm64/mm/dma-mapping.c | 75 ++++++++++++++--------

[...]

> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
> index a6e757c..ada00c3 100644
> --- a/arch/arm64/mm/dma-mapping.c
> +++ b/arch/arm64/mm/dma-mapping.c
> @@ -107,7 +107,7 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size,
> if (!page)
> return NULL;
>
> - *dma_handle = phys_to_dma(dev, page_to_phys(page));
> + *dma_handle = swiotlb_phys_to_dma(dev, page_to_phys(page));
> addr = page_address(page);
> memset(addr, 0, size);
> return addr;
> @@ -121,7 +121,7 @@ static void __dma_free_coherent(struct device *dev, size_t size,
> struct dma_attrs *attrs)
> {
> bool freed;
> - phys_addr_t paddr = dma_to_phys(dev, dma_handle);
> + phys_addr_t paddr = swiotlb_dma_to_phys(dev, dma_handle);
>
> if (dev == NULL) {
> WARN_ONCE(1, "Use an actual device structure for DMA allocation\n");
> @@ -151,7 +151,8 @@ static void *__dma_alloc(struct device *dev, size_t size,
> void *addr = __alloc_from_pool(size, &page, flags);
>
> if (addr)
> - *dma_handle = phys_to_dma(dev, page_to_phys(page));
> + *dma_handle = swiotlb_phys_to_dma(dev,
> + page_to_phys(page));
>
> return addr;
> }
> @@ -187,7 +188,7 @@ static void __dma_free(struct device *dev, size_t size,
> void *vaddr, dma_addr_t dma_handle,
> struct dma_attrs *attrs)
> {
> - void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle));
> + void *swiotlb_addr = phys_to_virt(swiotlb_dma_to_phys(dev, dma_handle));
>
> size = PAGE_ALIGN(size);
>
> @@ -208,7 +209,8 @@ static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
>
> dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs);
> if (!is_device_dma_coherent(dev))
> - __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
> + __dma_map_area(phys_to_virt(swiotlb_dma_to_phys(dev, dev_addr)),
> + size, dir);
>
> return dev_addr;
> }
> @@ -218,8 +220,11 @@ static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr,
> size_t size, enum dma_data_direction dir,
> struct dma_attrs *attrs)
> {
> - if (!is_device_dma_coherent(dev))
> - __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
> + if (!is_device_dma_coherent(dev)) {
> + phys_addr_t phys = swiotlb_dma_to_phys(dev, dev_addr);
> +
> + __dma_unmap_area(phys_to_virt(phys), size, dir);
> + }
> swiotlb_unmap_page(dev, dev_addr, size, dir, attrs);
> }
>
> @@ -232,9 +237,12 @@ static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
>
> ret = swiotlb_map_sg_attrs(dev, sgl, nelems, dir, attrs);
> if (!is_device_dma_coherent(dev))
> - for_each_sg(sgl, sg, ret, i)
> - __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
> - sg->length, dir);
> + for_each_sg(sgl, sg, ret, i) {
> + dma_addr_t dma = sg->dma_address;
> + phys_addr_t phys = swiotlb_dma_to_phys(dev, dma);
> +
> + __dma_map_area(phys_to_virt(phys), sg->length, dir);
> + }
>
> return ret;
> }
> @@ -248,9 +256,12 @@ static void __swiotlb_unmap_sg_attrs(struct device *dev,
> int i;
>
> if (!is_device_dma_coherent(dev))
> - for_each_sg(sgl, sg, nelems, i)
> - __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
> - sg->length, dir);
> + for_each_sg(sgl, sg, nelems, i) {
> + dma_addr_t dma = sg->dma_address;
> + phys_addr_t phys = swiotlb_dma_to_phys(dev, dma);
> +
> + __dma_unmap_area(phys_to_virt(phys), sg->length, dir);
> + }
> swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs);
> }
>
> @@ -258,8 +269,11 @@ static void __swiotlb_sync_single_for_cpu(struct device *dev,
> dma_addr_t dev_addr, size_t size,
> enum dma_data_direction dir)
> {
> - if (!is_device_dma_coherent(dev))
> - __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
> + if (!is_device_dma_coherent(dev)) {
> + phys_addr_t phys = swiotlb_dma_to_phys(dev, dev_addr);
> +
> + __dma_unmap_area(phys_to_virt(phys), size, dir);
> + }
> swiotlb_sync_single_for_cpu(dev, dev_addr, size, dir);
> }
>
> @@ -269,7 +283,8 @@ static void __swiotlb_sync_single_for_device(struct device *dev,
> {
> swiotlb_sync_single_for_device(dev, dev_addr, size, dir);
> if (!is_device_dma_coherent(dev))
> - __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
> + __dma_map_area(phys_to_virt(swiotlb_dma_to_phys(dev, dev_addr)),
> + size, dir);
> }
>
> static void __swiotlb_sync_sg_for_cpu(struct device *dev,
> @@ -280,9 +295,12 @@ static void __swiotlb_sync_sg_for_cpu(struct device *dev,
> int i;
>
> if (!is_device_dma_coherent(dev))
> - for_each_sg(sgl, sg, nelems, i)
> - __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
> - sg->length, dir);
> + for_each_sg(sgl, sg, nelems, i) {
> + dma_addr_t dma = sg->dma_address;
> + phys_addr_t phys = swiotlb_dma_to_phys(dev, dma);
> +
> + __dma_unmap_area(phys_to_virt(phys), sg->length, dir);
> + }
> swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir);
> }
>
> @@ -295,9 +313,12 @@ static void __swiotlb_sync_sg_for_device(struct device *dev,
>
> swiotlb_sync_sg_for_device(dev, sgl, nelems, dir);
> if (!is_device_dma_coherent(dev))
> - for_each_sg(sgl, sg, nelems, i)
> - __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
> - sg->length, dir);
> + for_each_sg(sgl, sg, nelems, i) {
> + dma_addr_t dma = sg->dma_address;
> + phys_addr_t phys = swiotlb_dma_to_phys(dev, dma);
> +
> + __dma_map_area(phys_to_virt(phys), sg->length, dir);
> + }
> }
>
> static int __swiotlb_mmap(struct device *dev,
> @@ -309,7 +330,7 @@ static int __swiotlb_mmap(struct device *dev,
> unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >>
> PAGE_SHIFT;
> unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
> - unsigned long pfn = dma_to_phys(dev, dma_addr) >> PAGE_SHIFT;
> + unsigned long pfn = swiotlb_dma_to_phys(dev, dma_addr) >> PAGE_SHIFT;
> unsigned long off = vma->vm_pgoff;
>
> vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot,
> @@ -334,9 +355,11 @@ static int __swiotlb_get_sgtable(struct device *dev, struct sg_table *sgt,
> {
> int ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
>
> - if (!ret)
> - sg_set_page(sgt->sgl, phys_to_page(dma_to_phys(dev, handle)),
> - PAGE_ALIGN(size), 0);
> + if (!ret) {
> + phys_addr_t phys = swiotlb_dma_to_phys(dev, handle);
> +
> + sg_set_page(sgt->sgl, phys_to_page(phys), PAGE_ALIGN(size), 0);
> + }
>
> return ret;
> }

Since we know for sure that swiotlb_to_phys is a no-op on arm64, it
might be cleaner to simply not reference it at all. I suppose we could
have some private local wrappers, e.g.:

#define swiotlb_to_virt(addr) phys_to_virt((phys_addr_t)(addr))

to keep the intent of the code clear (and just in case anyone ever
builds a system mad enough to warrant switching out that definition, but
I'd hope that never happens).

Otherwise, looks good - thanks for doing this!

Robin.

2016-03-18 13:51:44

by Sinan Kaya

[permalink] [raw]
Subject: Re: [PATCH 1/3] crypto: marvell/cesa - replace dma_to_phys with dma_map_single

On 3/18/2016 7:25 AM, Robin Murphy wrote:
> On 18/03/16 09:30, Boris Brezillon wrote:
>> On Thu, 17 Mar 2016 23:50:20 +0000
>> Russell King - ARM Linux <[email protected]> wrote:
>>
>>> On Thu, Mar 17, 2016 at 07:17:24PM -0400, [email protected] wrote:
>>>> What is the correct way? I don't want to write engine->sram_dma = sram
>>>
>>> Well, what the driver _is_ wanting to do is to go from a CPU physical
>>> address to a device DMA address. phys_to_dma() looks like the correct
>>> thing there to me, but I guess that's just an offset and doesn't take
>>> account of any IOMMU that may be in the way.
>>>
>>> If you have an IOMMU, then the whole phys_to_dma() thing is a total
>>> failure as it only does a linear translation, and there are no
>>> interfaces in the kernel to take account of an IOMMU in the way. So,
>>> it needs something designed for the job, implemented and discussed by
>>> the normal methods of proposing a new cross-arch interface for drivers
>>> to use.
>>>
>>> What I'm certain of, though, is that the change proposed in this patch
>>> will break current users of this driver: virt_to_page() on an address
>>> returned by ioremap() is completely undefined, and will result in
>>> either a kernel oops, or if not poking at memory which isn't a struct
>>> page, ultimately resulting in something that isn't SRAM being pointed
>>> to by "engine->sram_dma".
>>>
>>
>> Or we could just do
>>
>> engine->sram_dma = res->start;
>>
>> which is pretty much what the SRAM/genalloc code is doing already.
>
> As Russell points out this is yet another type of "set up a DMA master to access something other than kernel RAM" - there's already discussion in progress over how to handle this for dmaengine slaves[1], so gathering more use-cases might help distil exactly what the design of not-strictly-DMA-but-so-closely-coupled-it-can't-really-live-anywhere-else needs to be.
>
> Robin.
>
> [1]:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-March/414422.html
>

Thanks for the link.

dma_map_resource looks like to be the correct way of doing things. Just from
the purist point of view, a driver is not supposed to know the physical address
of a DMA address. That kills the intent of using DMA API. When programming descriptors,
the DMA addresses should be programmed not physical addresses so that the same
driver can be used in a system with IOMMU. The IOMMU DMA ops will remap the DMA
address to a bus address that is not physical address. All of this operation needs
to be isolated from the device driver.


I don't know the architecture or the driver enough to write this. This is not ideally
right but I can do this if Boris you are OK with this.

engine->sram_dma = res->start;

Another option is I can write

engine->sram_dma = swiotlb_dma_to_phys(res->start)

I agree that dma_map_single is not the right thing.

--
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

2016-03-18 13:55:33

by Sinan Kaya

[permalink] [raw]
Subject: Re: [PATCH 3/3] dma-mapping: move swiotlb dma-phys functions to common header

On 3/18/2016 7:31 AM, Robin Murphy wrote:
> On 17/03/16 22:02, Sinan Kaya wrote:
>> Moving the default implementation of swiotlb_dma_to_phys and
>> swiotlb_phys_to_dma functions to dma-mapping.h so that we can get
>> rid of the duplicate code in multiple ARCH.
>>
>> Signed-off-by: Sinan Kaya <[email protected]>
>> ---
>> arch/arm64/include/asm/dma-mapping.h | 14 --------------
>> arch/ia64/include/asm/dma-mapping.h | 14 --------------
>> arch/mips/include/asm/mach-generic/dma-coherence.h | 16 ----------------
>> arch/tile/include/asm/dma-mapping.h | 14 --------------
>> arch/unicore32/include/asm/dma-mapping.h | 14 --------------
>> arch/x86/include/asm/dma-mapping.h | 13 -------------
>> arch/xtensa/include/asm/dma-mapping.h | 14 --------------
>> include/linux/dma-mapping.h | 14 ++++++++++++++
>> 8 files changed, 14 insertions(+), 99 deletions(-)
>
> [...]
>
>> diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
>> index 728ef07..871d620 100644
>> --- a/include/linux/dma-mapping.h
>> +++ b/include/linux/dma-mapping.h
>> @@ -683,4 +683,18 @@ static inline int dma_mmap_writecombine(struct device *dev,
>> #define dma_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
>> #endif
>>
>> +#ifndef swiotlb_phys_to_dma
>> +static inline dma_addr_t swiotlb_phys_to_dma(struct device *dev, phys_addr_t paddr)
>> +{
>> + return paddr;
>> +}
>> +#endif
>> +
>> +#ifndef swiotlb_dma_to_phys
>> +static inline phys_addr_t swiotlb_dma_to_phys(struct device *dev, dma_addr_t daddr)
>> +{
>> + return daddr;
>> +}
>> +#endif
>> +
>> #endif
>>
>
> Could the default definition not be pushed all the way down into swiotlb.c (or at least swiotlb.h)?

I can do that but then we lose the inlining capability of the compiler. This could cost
performance penalty on architectures using it.

I tried moving it to swiotlb.h. swiotlb.h seems to be only used by swiotlb.c file. I could try
including it into dma-mapping.h and then moving the definitions into swiotlb.h file.

Let me give this a try.

>
> Robin.
>


--
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

2016-03-18 14:01:00

by Sinan Kaya

[permalink] [raw]
Subject: Re: [PATCH 1/3] crypto: marvell/cesa - replace dma_to_phys with dma_map_single

On 3/18/2016 9:51 AM, Sinan Kaya wrote:
> Another option is I can write
>
> engine->sram_dma = swiotlb_dma_to_phys(res->start)

I realized that I made a mistake in the commit message and the code above.

The code is trying to find DMA address from physical address. Not the other
way around. I'll fix it on the next version.

The correct suggestion above would be

engine->sram_dma = swiotlb_phys_to_dmares->start)

--
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

2016-03-18 14:20:51

by Boris Brezillon

[permalink] [raw]
Subject: Re: [PATCH 1/3] crypto: marvell/cesa - replace dma_to_phys with dma_map_single

On Fri, 18 Mar 2016 09:51:37 -0400
Sinan Kaya <[email protected]> wrote:

> On 3/18/2016 7:25 AM, Robin Murphy wrote:
> > On 18/03/16 09:30, Boris Brezillon wrote:
> >> On Thu, 17 Mar 2016 23:50:20 +0000
> >> Russell King - ARM Linux <[email protected]> wrote:
> >>
> >>> On Thu, Mar 17, 2016 at 07:17:24PM -0400, [email protected] wrote:
> >>>> What is the correct way? I don't want to write engine->sram_dma = sram
> >>>
> >>> Well, what the driver _is_ wanting to do is to go from a CPU physical
> >>> address to a device DMA address. phys_to_dma() looks like the correct
> >>> thing there to me, but I guess that's just an offset and doesn't take
> >>> account of any IOMMU that may be in the way.
> >>>
> >>> If you have an IOMMU, then the whole phys_to_dma() thing is a total
> >>> failure as it only does a linear translation, and there are no
> >>> interfaces in the kernel to take account of an IOMMU in the way. So,
> >>> it needs something designed for the job, implemented and discussed by
> >>> the normal methods of proposing a new cross-arch interface for drivers
> >>> to use.
> >>>
> >>> What I'm certain of, though, is that the change proposed in this patch
> >>> will break current users of this driver: virt_to_page() on an address
> >>> returned by ioremap() is completely undefined, and will result in
> >>> either a kernel oops, or if not poking at memory which isn't a struct
> >>> page, ultimately resulting in something that isn't SRAM being pointed
> >>> to by "engine->sram_dma".
> >>>
> >>
> >> Or we could just do
> >>
> >> engine->sram_dma = res->start;
> >>
> >> which is pretty much what the SRAM/genalloc code is doing already.
> >
> > As Russell points out this is yet another type of "set up a DMA master to access something other than kernel RAM" - there's already discussion in progress over how to handle this for dmaengine slaves[1], so gathering more use-cases might help distil exactly what the design of not-strictly-DMA-but-so-closely-coupled-it-can't-really-live-anywhere-else needs to be.
> >
> > Robin.
> >
> > [1]:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-March/414422.html
> >
>
> Thanks for the link.
>
> dma_map_resource looks like to be the correct way of doing things. Just from
> the purist point of view, a driver is not supposed to know the physical address
> of a DMA address. That kills the intent of using DMA API. When programming descriptors,
> the DMA addresses should be programmed not physical addresses so that the same
> driver can be used in a system with IOMMU. The IOMMU DMA ops will remap the DMA
> address to a bus address that is not physical address. All of this operation needs
> to be isolated from the device driver.
>
>
> I don't know the architecture or the driver enough to write this. This is not ideally
> right but I can do this if Boris you are OK with this.
>
> engine->sram_dma = res->start;

I don't know.

How about waiting for the 'dma_{map,unmap}_resource' discussion to
settle down before removing phy_to_dma()/dma_to_phys() APIs (as
suggested by Robin and Russell)?


--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

2016-03-18 14:21:49

by Sinan Kaya

[permalink] [raw]
Subject: Re: [PATCH 1/3] crypto: marvell/cesa - replace dma_to_phys with dma_map_single

On 3/18/2016 10:20 AM, Boris Brezillon wrote:
> On Fri, 18 Mar 2016 09:51:37 -0400
> Sinan Kaya <[email protected]> wrote:
>
>> On 3/18/2016 7:25 AM, Robin Murphy wrote:
>>> On 18/03/16 09:30, Boris Brezillon wrote:
>>>> On Thu, 17 Mar 2016 23:50:20 +0000
>>>> Russell King - ARM Linux <[email protected]> wrote:
>>>>
>>>>> On Thu, Mar 17, 2016 at 07:17:24PM -0400, [email protected] wrote:
>>>>>> What is the correct way? I don't want to write engine->sram_dma = sram
>>>>>
>>>>> Well, what the driver _is_ wanting to do is to go from a CPU physical
>>>>> address to a device DMA address. phys_to_dma() looks like the correct
>>>>> thing there to me, but I guess that's just an offset and doesn't take
>>>>> account of any IOMMU that may be in the way.
>>>>>
>>>>> If you have an IOMMU, then the whole phys_to_dma() thing is a total
>>>>> failure as it only does a linear translation, and there are no
>>>>> interfaces in the kernel to take account of an IOMMU in the way. So,
>>>>> it needs something designed for the job, implemented and discussed by
>>>>> the normal methods of proposing a new cross-arch interface for drivers
>>>>> to use.
>>>>>
>>>>> What I'm certain of, though, is that the change proposed in this patch
>>>>> will break current users of this driver: virt_to_page() on an address
>>>>> returned by ioremap() is completely undefined, and will result in
>>>>> either a kernel oops, or if not poking at memory which isn't a struct
>>>>> page, ultimately resulting in something that isn't SRAM being pointed
>>>>> to by "engine->sram_dma".
>>>>>
>>>>
>>>> Or we could just do
>>>>
>>>> engine->sram_dma = res->start;
>>>>
>>>> which is pretty much what the SRAM/genalloc code is doing already.
>>>
>>> As Russell points out this is yet another type of "set up a DMA master to access something other than kernel RAM" - there's already discussion in progress over how to handle this for dmaengine slaves[1], so gathering more use-cases might help distil exactly what the design of not-strictly-DMA-but-so-closely-coupled-it-can't-really-live-anywhere-else needs to be.
>>>
>>> Robin.
>>>
>>> [1]:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-March/414422.html
>>>
>>
>> Thanks for the link.
>>
>> dma_map_resource looks like to be the correct way of doing things. Just from
>> the purist point of view, a driver is not supposed to know the physical address
>> of a DMA address. That kills the intent of using DMA API. When programming descriptors,
>> the DMA addresses should be programmed not physical addresses so that the same
>> driver can be used in a system with IOMMU. The IOMMU DMA ops will remap the DMA
>> address to a bus address that is not physical address. All of this operation needs
>> to be isolated from the device driver.
>>
>>
>> I don't know the architecture or the driver enough to write this. This is not ideally
>> right but I can do this if Boris you are OK with this.
>>
>> engine->sram_dma = res->start;
>
> I don't know.
>
> How about waiting for the 'dma_{map,unmap}_resource' discussion to
> settle down before removing phy_to_dma()/dma_to_phys() APIs (as
> suggested by Robin and Russell)?
>
>

Sure, that's fine for me.

--
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

2016-03-18 15:00:33

by Sinan Kaya

[permalink] [raw]
Subject: Re: [PATCH 2/3] swiotlb: prefix dma_to_phys and phys_to_dma functions

On 3/18/2016 8:12 AM, Robin Murphy wrote:
> Since we know for sure that swiotlb_to_phys is a no-op on arm64, it might be cleaner to simply not reference it at all. I suppose we could have some private local wrappers, e.g.:
>
> #define swiotlb_to_virt(addr) phys_to_virt((phys_addr_t)(addr))
>
> to keep the intent of the code clear (and just in case anyone ever builds a system mad enough to warrant switching out that definition, but I'd hope that never happens).
>
> Otherwise, looks good - thanks for doing this!

OK. I added this. Reviewed-by?

I'm not happy to submit such a big patch for all different ARCHs. I couldn't
find a cleaner solution. I'm willing to split this patch into multiple if there
is a better way.

diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index ada00c3..8c0f66b 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -29,6 +29,14 @@

#include <asm/cacheflush.h>

+/*
+ * If you are building a system without IOMMU, then you are using SWIOTLB
+ * library. The ARM64 adaptation of this library does not support address
+ * translation and it assumes that physical address = dma address for such
+ * a use case. Please don't build a platform that violates this.
+ */
+#define swiotlb_to_virt(addr) phys_to_virt((phys_addr_t)(addr))
+
static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot,
bool coherent)
{
@@ -188,7 +196,7 @@ static void __dma_free(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
struct dma_attrs *attrs)
{
- void *swiotlb_addr = phys_to_virt(swiotlb_dma_to_phys(dev, dma_handle));
+ void *swiotlb_addr = swiotlb_to_virt(dma_handle);

size = PAGE_ALIGN(size);

@@ -209,8 +217,7 @@ static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,

dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs);
if (!is_device_dma_coherent(dev))
- __dma_map_area(phys_to_virt(swiotlb_dma_to_phys(dev, dev_addr)),
- size, dir);
+ __dma_map_area(swiotlb_to_virt(dev_addr), size, dir);

return dev_addr;
}
@@ -283,8 +290,7 @@ static void __swiotlb_sync_single_for_device(struct device *dev,
{
swiotlb_sync_single_for_device(dev, dev_addr, size, dir);
if (!is_device_dma_coherent(dev))
- __dma_map_area(phys_to_virt(swiotlb_dma_to_phys(dev, dev_addr)),
- size, dir);
+ __dma_map_area(swiotlb_to_virt(dev_addr), size, dir);
}




--
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

2016-03-18 20:20:16

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 1/3] crypto: marvell/cesa - replace dma_to_phys with dma_map_single

Hi Sinan,

[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on v4.5 next-20160318]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url: https://github.com/0day-ci/linux/commits/Sinan-Kaya/crypto-marvell-cesa-replace-dma_to_phys-with-dma_map_single/20160318-060640
base: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux for-next/core
config: arm-allmodconfig (attached as .config)
reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm

All errors (new ones prefixed by >>):

drivers/crypto/marvell/cesa.c: In function 'mv_cesa_get_sram':
>> drivers/crypto/marvell/cesa.c:354:21: error: macro "dma_map_single" requires 4 arguments, but only 3 given
DMA_TO_DEVICE);
^
>> drivers/crypto/marvell/cesa.c:353:21: error: 'dma_map_single' undeclared (first use in this function)
engine->sram_dma = dma_map_single(cesa->dev, engine->sram,
^
drivers/crypto/marvell/cesa.c:353:21: note: each undeclared identifier is reported only once for each function it appears in

vim +/dma_map_single +354 drivers/crypto/marvell/cesa.c

347 return -EINVAL;
348
349 engine->sram = devm_ioremap_resource(cesa->dev, res);
350 if (IS_ERR(engine->sram))
351 return PTR_ERR(engine->sram);
352
> 353 engine->sram_dma = dma_map_single(cesa->dev, engine->sram,
> 354 DMA_TO_DEVICE);
355
356 return 0;
357 }

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation


Attachments:
(No filename) (1.79 kB)
.config.gz (54.90 kB)
Download all attachments

2016-03-28 18:29:36

by Konrad Rzeszutek Wilk

[permalink] [raw]
Subject: Re: [PATCH 2/3] swiotlb: prefix dma_to_phys and phys_to_dma functions

On Fri, Mar 18, 2016 at 11:00 AM, Sinan Kaya <[email protected]> wrote:
> On 3/18/2016 8:12 AM, Robin Murphy wrote:
>> Since we know for sure that swiotlb_to_phys is a no-op on arm64, it might be cleaner to simply not reference it at all. I suppose we could have some private local wrappers, e.g.:
>>
>> #define swiotlb_to_virt(addr) phys_to_virt((phys_addr_t)(addr))
>>
>> to keep the intent of the code clear (and just in case anyone ever builds a system mad enough to warrant switching out that definition, but I'd hope that never happens).
>>
>> Otherwise, looks good - thanks for doing this!
>
> OK. I added this. Reviewed-by?
>
> I'm not happy to submit such a big patch for all different ARCHs. I couldn't
> find a cleaner solution. I'm willing to split this patch into multiple if there
> is a better way.
>
> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
> index ada00c3..8c0f66b 100644
> --- a/arch/arm64/mm/dma-mapping.c
> +++ b/arch/arm64/mm/dma-mapping.c
> @@ -29,6 +29,14 @@
>
> #include <asm/cacheflush.h>
>
> +/*
> + * If you are building a system without IOMMU, then you are using SWIOTLB
> + * library. The ARM64 adaptation of this library does not support address
> + * translation and it assumes that physical address = dma address for such
> + * a use case. Please don't build a platform that violates this.
> + */

Why not just expand the ARM64 part to support address translation?

> +#define swiotlb_to_virt(addr) phys_to_virt((phys_addr_t)(addr))
> +

Adding Stefano here.

> static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot,
> bool coherent)
> {
> @@ -188,7 +196,7 @@ static void __dma_free(struct device *dev, size_t size,
> void *vaddr, dma_addr_t dma_handle,
> struct dma_attrs *attrs)
> {
> - void *swiotlb_addr = phys_to_virt(swiotlb_dma_to_phys(dev, dma_handle));
> + void *swiotlb_addr = swiotlb_to_virt(dma_handle);
>
> size = PAGE_ALIGN(size);
>
> @@ -209,8 +217,7 @@ static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
>
> dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs);
> if (!is_device_dma_coherent(dev))
> - __dma_map_area(phys_to_virt(swiotlb_dma_to_phys(dev, dev_addr)),
> - size, dir);
> + __dma_map_area(swiotlb_to_virt(dev_addr), size, dir);
>
> return dev_addr;
> }
> @@ -283,8 +290,7 @@ static void __swiotlb_sync_single_for_device(struct device *dev,
> {
> swiotlb_sync_single_for_device(dev, dev_addr, size, dir);
> if (!is_device_dma_coherent(dev))
> - __dma_map_area(phys_to_virt(swiotlb_dma_to_phys(dev, dev_addr)),
> - size, dir);
> + __dma_map_area(swiotlb_to_virt(dev_addr), size, dir);
> }
>
>
>
>
> --
> Sinan Kaya
> Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

2016-03-29 12:46:01

by Stefano Stabellini

[permalink] [raw]
Subject: Re: [PATCH 2/3] swiotlb: prefix dma_to_phys and phys_to_dma functions

On Mon, 28 Mar 2016, Konrad Rzeszutek Wilk wrote:
> On Fri, Mar 18, 2016 at 11:00 AM, Sinan Kaya <[email protected]> wrote:
> > On 3/18/2016 8:12 AM, Robin Murphy wrote:
> >> Since we know for sure that swiotlb_to_phys is a no-op on arm64, it might be cleaner to simply not reference it at all. I suppose we could have some private local wrappers, e.g.:
> >>
> >> #define swiotlb_to_virt(addr) phys_to_virt((phys_addr_t)(addr))
> >>
> >> to keep the intent of the code clear (and just in case anyone ever builds a system mad enough to warrant switching out that definition, but I'd hope that never happens).
> >>
> >> Otherwise, looks good - thanks for doing this!
> >
> > OK. I added this. Reviewed-by?
> >
> > I'm not happy to submit such a big patch for all different ARCHs. I couldn't
> > find a cleaner solution. I'm willing to split this patch into multiple if there
> > is a better way.
> >
> > diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
> > index ada00c3..8c0f66b 100644
> > --- a/arch/arm64/mm/dma-mapping.c
> > +++ b/arch/arm64/mm/dma-mapping.c
> > @@ -29,6 +29,14 @@
> >
> > #include <asm/cacheflush.h>
> >
> > +/*
> > + * If you are building a system without IOMMU, then you are using SWIOTLB
> > + * library. The ARM64 adaptation of this library does not support address
> > + * translation and it assumes that physical address = dma address for such
> > + * a use case. Please don't build a platform that violates this.
> > + */
>
> Why not just expand the ARM64 part to support address translation?
>
> > +#define swiotlb_to_virt(addr) phys_to_virt((phys_addr_t)(addr))
> > +
>
> Adding Stefano here.

Could you please explain what is the problem that you are trying to
solve? In other words, what is the issue with assuming that physical
address = dma address (and the current dma_to_phys and phys_to_dma
static inlines) if no arm64 platforms violate it? That's pretty much
what is done on x86 too (without X86_DMA_REMAP).

If you want to make sure that the assumption is not violated, you can
introduce a boot time check or a BUG_ON somewhere.

If there is an arm64 platform with phys_addr != dma_addr, we need proper
support for it. In fact even if there is an IOMMU on that platform, when
running Xen on it, the IOMMU would be used by the hypervisor and Linux
would still end up without it, using the swiotlb.


> > static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot,
> > bool coherent)
> > {
> > @@ -188,7 +196,7 @@ static void __dma_free(struct device *dev, size_t size,
> > void *vaddr, dma_addr_t dma_handle,
> > struct dma_attrs *attrs)
> > {
> > - void *swiotlb_addr = phys_to_virt(swiotlb_dma_to_phys(dev, dma_handle));
> > + void *swiotlb_addr = swiotlb_to_virt(dma_handle);
> >
> > size = PAGE_ALIGN(size);
> >
> > @@ -209,8 +217,7 @@ static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
> >
> > dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs);
> > if (!is_device_dma_coherent(dev))
> > - __dma_map_area(phys_to_virt(swiotlb_dma_to_phys(dev, dev_addr)),
> > - size, dir);
> > + __dma_map_area(swiotlb_to_virt(dev_addr), size, dir);
> >
> > return dev_addr;
> > }
> > @@ -283,8 +290,7 @@ static void __swiotlb_sync_single_for_device(struct device *dev,
> > {
> > swiotlb_sync_single_for_device(dev, dev_addr, size, dir);
> > if (!is_device_dma_coherent(dev))
> > - __dma_map_area(phys_to_virt(swiotlb_dma_to_phys(dev, dev_addr)),
> > - size, dir);
> > + __dma_map_area(swiotlb_to_virt(dev_addr), size, dir);
> > }
> >
> >
> >
> >
> > --
> > Sinan Kaya
> > Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
> > Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
>

2016-03-29 12:57:55

by Sinan Kaya

[permalink] [raw]
Subject: Re: [PATCH 2/3] swiotlb: prefix dma_to_phys and phys_to_dma functions

On 3/29/2016 8:44 AM, Stefano Stabellini wrote:
> Could you please explain what is the problem that you are trying to
> solve? In other words, what is the issue with assuming that physical
> address = dma address (and the current dma_to_phys and phys_to_dma
> static inlines) if no arm64 platforms violate it? That's pretty much
> what is done on x86 too (without X86_DMA_REMAP).
>
> If you want to make sure that the assumption is not violated, you can
> introduce a boot time check or a BUG_ON somewhere.
>
> If there is an arm64 platform with phys_addr != dma_addr, we need proper
> support for it. In fact even if there is an IOMMU on that platform, when
> running Xen on it, the IOMMU would be used by the hypervisor and Linux
> would still end up without it, using the swiotlb.


The problem is that device drivers are trying to use dma_to_phys and phys_to_dma
APIs to do address translation even though these two API do not exist in DMA mapping
layer. (see patch #1 and I made the same mistake in my HIDMA code)

Especially, when a device is behind an IOMMU; the DMA addresses are not equal
to physical addresses. Usage of dma_to_phys causes a crash on the system.

I'm trying to prefix the dma_to_phys and phys_to_dma API with swiotlb so that
we know what it is intended for and usage of these API in drivers need to be
discouraged in the future during code reviews.

Since I renamed the API, Robin Murphy made a suggestion to convert this

phys_to_virt(swiotlb_dma_to_phys(dev, dma_handle))

to this

#define swiotlb_to_virt(addr) phys_to_virt((phys_addr_t)(addr))

swiotlb_to_virt(dma_handle)

just to reduce code clutter since we know swiotlb_dma_to_phys returns phys already
for ARM64 architecture.

I think we can do this exercise later. I'll undo this change for the moment.
Let's focus on the API rename.

I don't want this general purpose dma_to_phys API returning phys=dma value. This is
not correct.

--
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

2016-03-29 19:36:17

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 2/3] swiotlb: prefix dma_to_phys and phys_to_dma functions

On Monday 28 March 2016 14:29:29 Konrad Rzeszutek Wilk wrote:
> > diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
> > index ada00c3..8c0f66b 100644
> > --- a/arch/arm64/mm/dma-mapping.c
> > +++ b/arch/arm64/mm/dma-mapping.c
> > @@ -29,6 +29,14 @@
> >
> > #include <asm/cacheflush.h>
> >
> > +/*
> > + * If you are building a system without IOMMU, then you are using SWIOTLB
> > + * library. The ARM64 adaptation of this library does not support address
> > + * translation and it assumes that physical address = dma address for such
> > + * a use case. Please don't build a platform that violates this.
> > + */
>
> Why not just expand the ARM64 part to support address translation?

Because so far all hardware we have is relatively sane. We only
need to implement this if someone accidentally puts their DMA
space at the wrong address.

There is at least one platform that could in theory use this because
their RAM starts at an address that is outside of the reach of 32-bit
devices, and a static IOMMU mapping (created by firmware) could be
used to map the start of RAM into DMA address zero, to avoid having
to use an IOMMU all the time, but it was considered not worth the
effort to implement that.

Arnd