Netdev Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants
@ 2019-11-13 12:24 Laurentiu Tudor
  2019-11-13 12:24 ` [PATCH v3 1/4] dma-mapping: introduce new dma unmap and sync api variants Laurentiu Tudor
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Laurentiu Tudor @ 2019-11-13 12:24 UTC (permalink / raw)
  To: hch, robin.murphy, joro, Ioana Ciocoi Radulescu, linux-kernel,
	iommu, netdev, Ioana Ciornei
  Cc: Leo Li, Diana Madalina Craciun, davem, Madalin Bucur,
	Camelia Alexandra Groza, Laurentiu Tudor

From: Laurentiu Tudor <laurentiu.tudor@nxp.com>

This series introduces a few new dma unmap and sync api variants that,
on top of what the originals do, return the virtual address
corresponding to the input dma address. In order to do that a new dma
map op is added, .get_virt_addr that takes the input dma address and
returns the virtual address backing it up.
The second patch adds an implementation for this new dma map op in the
generic iommu dma glue code and wires it in.
The third patch updates the dpaa2-eth driver to use the new apis.

Context: https://lkml.org/lkml/2019/5/31/684

Changes in v3
 * drop useless check for null iommu domain (Robin)
 * add dma_can_unmap_by_dma_addr() to check availability of
   these new apis (Christoph)
 * make apis work with direct dma (Christoph)
 * add support for swiotlb (Robin)
 * simplify dpaa2_eth driver code by using dma_unmap_single_desc()
   instead of dma_unmap_page_desc()

Changes in v2
 * use "dma_unmap_*_desc" names (Robin)
 * return va/page instead of phys addr (Robin)

Changes since RFC
 * completely changed the approach: added unmap and sync variants that
   return the phys addr instead of adding a new dma to phys conversion
   function

Laurentiu Tudor (4):
  dma-mapping: introduce new dma unmap and sync api variants
  iommu/dma: wire-up new dma map op .get_virt_addr
  swiotlb: make new {unmap,sync}_desc dma apis work with swiotlb
  dpaa2_eth: use new unmap and sync dma api variants

 drivers/iommu/dma-iommu.c                     | 13 ++++
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  | 43 +++++-----
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.h  |  1 -
 include/linux/dma-mapping.h                   | 45 +++++++++++
 include/linux/swiotlb.h                       |  7 ++
 kernel/dma/mapping.c                          | 78 +++++++++++++++++++
 kernel/dma/swiotlb.c                          |  8 ++
 7 files changed, 169 insertions(+), 26 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v3 1/4] dma-mapping: introduce new dma unmap and sync api variants
  2019-11-13 12:24 [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants Laurentiu Tudor
@ 2019-11-13 12:24 ` Laurentiu Tudor
  2019-11-13 12:24 ` [PATCH v3 2/4] iommu/dma: wire-up new dma map op .get_virt_addr Laurentiu Tudor
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Laurentiu Tudor @ 2019-11-13 12:24 UTC (permalink / raw)
  To: hch, robin.murphy, joro, Ioana Ciocoi Radulescu, linux-kernel,
	iommu, netdev, Ioana Ciornei
  Cc: Leo Li, Diana Madalina Craciun, davem, Madalin Bucur,
	Camelia Alexandra Groza, Laurentiu Tudor

From: Laurentiu Tudor <laurentiu.tudor@nxp.com>

Introduce a few new dma unmap and sync variants that, on top of the
original variants, return the virtual address corresponding to the
input dma address. Additionally, provide an api that can be used to
check at runtime if these variants are actually available.
In order to implement them, a new dma map op is added and used:
    void *get_virt_addr(dev, dma_handle);
It does the actual conversion of an input dma address to the output
virtual address.

Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
---
 include/linux/dma-mapping.h | 45 +++++++++++++++++++++++++++++++
 kernel/dma/mapping.c        | 53 +++++++++++++++++++++++++++++++++++++
 2 files changed, 98 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 4a1c4fca475a..0940bd75df8e 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -132,6 +132,7 @@ struct dma_map_ops {
 	u64 (*get_required_mask)(struct device *dev);
 	size_t (*max_mapping_size)(struct device *dev);
 	unsigned long (*get_merge_boundary)(struct device *dev);
+	void *(*get_virt_addr)(struct device *dev, dma_addr_t dma_handle);
 };
 
 #define DMA_MAPPING_ERROR		(~(dma_addr_t)0)
@@ -442,6 +443,13 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 	return 0;
 }
 
+static inline bool dma_can_unmap_by_dma_addr(struct device *dev)
+{
+	const struct dma_map_ops *ops = get_dma_ops(dev);
+
+	return dma_is_direct(ops) || (ops && ops->get_virt_addr);
+}
+
 void *dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
 		gfp_t flag, unsigned long attrs);
 void dma_free_attrs(struct device *dev, size_t size, void *cpu_addr,
@@ -458,6 +466,14 @@ int dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt,
 int dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
 		void *cpu_addr, dma_addr_t dma_addr, size_t size,
 		unsigned long attrs);
+void *dma_unmap_single_attrs_desc(struct device *dev, dma_addr_t addr,
+				  size_t size, enum dma_data_direction dir,
+				  unsigned long attrs);
+struct page *
+dma_unmap_page_attrs_desc(struct device *dev, dma_addr_t addr, size_t size,
+			  enum dma_data_direction dir, unsigned long attrs);
+void *dma_sync_single_for_cpu_desc(struct device *dev, dma_addr_t addr,
+				   size_t size, enum dma_data_direction dir);
 bool dma_can_mmap(struct device *dev);
 int dma_supported(struct device *dev, u64 mask);
 int dma_set_mask(struct device *dev, u64 mask);
@@ -534,6 +550,27 @@ static inline void dmam_free_coherent(struct device *dev, size_t size,
 		void *vaddr, dma_addr_t dma_handle)
 {
 }
+
+static inline void *
+dma_unmap_single_attrs_desc(struct device *dev, dma_addr_t addr, size_t size,
+			    enum dma_data_direction dir, unsigned long attrs)
+{
+	return NULL;
+}
+
+static inline struct page *
+dma_unmap_page_attrs_desc(struct device *dev, dma_addr_t addr, size_t size,
+			  enum dma_data_direction dir, unsigned long attrs)
+{
+	return NULL;
+}
+
+static inline void *
+dma_sync_single_for_cpu_desc(struct device *dev, dma_addr_t addr, size_t size,
+			     enum dma_data_direction dir)
+{
+	return NULL;
+}
 static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 		enum dma_data_direction dir)
 {
@@ -578,6 +615,11 @@ static inline unsigned long dma_get_merge_boundary(struct device *dev)
 {
 	return 0;
 }
+
+static inline bool dma_can_unmap_by_dma_addr(struct device *dev)
+{
+	return false;
+}
 #endif /* CONFIG_HAS_DMA */
 
 static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
@@ -610,10 +652,13 @@ static inline void dma_sync_single_range_for_device(struct device *dev,
 
 #define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, 0)
 #define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, 0)
+#define dma_unmap_single_desc(d, a, s, r) \
+		dma_unmap_single_attrs_desc(d, a, s, r, 0)
 #define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
 #define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
 #define dma_map_page(d, p, o, s, r) dma_map_page_attrs(d, p, o, s, r, 0)
 #define dma_unmap_page(d, a, s, r) dma_unmap_page_attrs(d, a, s, r, 0)
+#define dma_unmap_page_desc(d, a, s, r) dma_unmap_page_attrs_desc(d, a, s, r, 0)
 #define dma_get_sgtable(d, t, v, h, s) dma_get_sgtable_attrs(d, t, v, h, s, 0)
 #define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, 0)
 
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index d9334f31a5af..2b6f245c9bb1 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -345,6 +345,59 @@ void dma_free_attrs(struct device *dev, size_t size, void *cpu_addr,
 }
 EXPORT_SYMBOL(dma_free_attrs);
 
+struct page *
+dma_unmap_page_attrs_desc(struct device *dev, dma_addr_t addr, size_t size,
+			  enum dma_data_direction dir, unsigned long attrs)
+{
+	const struct dma_map_ops *ops = get_dma_ops(dev);
+	void *ptr = NULL;
+
+	if (dma_is_direct(ops))
+		ptr = phys_to_virt(dma_to_phys(dev, addr));
+	else if (ops && ops->get_virt_addr)
+		ptr = ops->get_virt_addr(dev, addr);
+
+	dma_unmap_page_attrs(dev, addr, size, dir, attrs);
+
+	return ptr ? virt_to_page(ptr) : NULL;
+}
+EXPORT_SYMBOL_GPL(dma_unmap_page_attrs_desc);
+
+void *dma_unmap_single_attrs_desc(struct device *dev, dma_addr_t addr,
+				  size_t size, enum dma_data_direction dir,
+				  unsigned long attrs)
+{
+	const struct dma_map_ops *ops = get_dma_ops(dev);
+	void *ptr = NULL;
+
+	if (dma_is_direct(ops))
+		ptr = phys_to_virt(dma_to_phys(dev, addr));
+	else if (ops && ops->get_virt_addr)
+		ptr = ops->get_virt_addr(dev, addr);
+
+	dma_unmap_single_attrs(dev, addr, size, dir, attrs);
+
+	return ptr;
+}
+EXPORT_SYMBOL_GPL(dma_unmap_single_attrs_desc);
+
+void *dma_sync_single_for_cpu_desc(struct device *dev, dma_addr_t addr,
+				   size_t size, enum dma_data_direction dir)
+{
+	const struct dma_map_ops *ops = get_dma_ops(dev);
+	void *ptr = NULL;
+
+	if (dma_is_direct(ops))
+		ptr = phys_to_virt(dma_to_phys(dev, addr));
+	else if (ops && ops->get_virt_addr)
+		ptr = ops->get_virt_addr(dev, addr);
+
+	dma_sync_single_for_cpu(dev, addr, size, dir);
+
+	return ptr;
+}
+EXPORT_SYMBOL_GPL(dma_sync_single_for_cpu_desc);
+
 int dma_supported(struct device *dev, u64 mask)
 {
 	const struct dma_map_ops *ops = get_dma_ops(dev);
-- 
2.17.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v3 2/4] iommu/dma: wire-up new dma map op .get_virt_addr
  2019-11-13 12:24 [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants Laurentiu Tudor
  2019-11-13 12:24 ` [PATCH v3 1/4] dma-mapping: introduce new dma unmap and sync api variants Laurentiu Tudor
@ 2019-11-13 12:24 ` Laurentiu Tudor
  2019-11-13 12:24 ` [PATCH v3 3/4] swiotlb: make new {unmap,sync}_desc dma apis work with swiotlb Laurentiu Tudor
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Laurentiu Tudor @ 2019-11-13 12:24 UTC (permalink / raw)
  To: hch, robin.murphy, joro, Ioana Ciocoi Radulescu, linux-kernel,
	iommu, netdev, Ioana Ciornei
  Cc: Leo Li, Diana Madalina Craciun, davem, Madalin Bucur,
	Camelia Alexandra Groza, Laurentiu Tudor

From: Laurentiu Tudor <laurentiu.tudor@nxp.com>

Add an implementation of the newly introduced dma map op in the
generic DMA IOMMU generic glue layer and wire it up.

Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
---
 drivers/iommu/dma-iommu.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index f321279baf9e..98742c1451ce 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -1091,6 +1091,18 @@ static unsigned long iommu_dma_get_merge_boundary(struct device *dev)
 	return (1UL << __ffs(domain->pgsize_bitmap)) - 1;
 }
 
+static void *iommu_dma_get_virt_addr(struct device *dev, dma_addr_t dma_handle)
+{
+	struct iommu_domain *domain = iommu_get_dma_domain(dev);
+	phys_addr_t phys;
+
+	phys = iommu_iova_to_phys(domain, dma_handle);
+	if (phys)
+		return phys_to_virt(phys);
+
+	return NULL;
+}
+
 static const struct dma_map_ops iommu_dma_ops = {
 	.alloc			= iommu_dma_alloc,
 	.free			= iommu_dma_free,
@@ -1107,6 +1119,7 @@ static const struct dma_map_ops iommu_dma_ops = {
 	.map_resource		= iommu_dma_map_resource,
 	.unmap_resource		= iommu_dma_unmap_resource,
 	.get_merge_boundary	= iommu_dma_get_merge_boundary,
+	.get_virt_addr		= iommu_dma_get_virt_addr,
 };
 
 /*
-- 
2.17.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v3 3/4] swiotlb: make new {unmap,sync}_desc dma apis work with swiotlb
  2019-11-13 12:24 [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants Laurentiu Tudor
  2019-11-13 12:24 ` [PATCH v3 1/4] dma-mapping: introduce new dma unmap and sync api variants Laurentiu Tudor
  2019-11-13 12:24 ` [PATCH v3 2/4] iommu/dma: wire-up new dma map op .get_virt_addr Laurentiu Tudor
@ 2019-11-13 12:24 ` Laurentiu Tudor
  2019-11-13 12:24 ` [PATCH v3 4/4] dpaa2_eth: use new unmap and sync dma api variants Laurentiu Tudor
  2019-11-13 20:11 ` [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants David Miller
  4 siblings, 0 replies; 10+ messages in thread
From: Laurentiu Tudor @ 2019-11-13 12:24 UTC (permalink / raw)
  To: hch, robin.murphy, joro, Ioana Ciocoi Radulescu, linux-kernel,
	iommu, netdev, Ioana Ciornei
  Cc: Leo Li, Diana Madalina Craciun, davem, Madalin Bucur,
	Camelia Alexandra Groza, Laurentiu Tudor

From: Laurentiu Tudor <laurentiu.tudor@nxp.com>

Add a new swiotlb helper to retrieve the original physical
address given a swiotlb physical address and use it in the new
dma_unmap_single_attrs_desc(), dma_sync_single_for_cpu_desc() and
dma_unmap_page_attrs_desc() APIs to make them work with swiotlb.

Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
---
 include/linux/swiotlb.h |  7 +++++++
 kernel/dma/mapping.c    | 43 ++++++++++++++++++++++++++++++++---------
 kernel/dma/swiotlb.c    |  8 ++++++++
 3 files changed, 49 insertions(+), 9 deletions(-)

diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index cde3dc18e21a..7a6883a71649 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -73,6 +73,8 @@ static inline bool is_swiotlb_buffer(phys_addr_t paddr)
 	return paddr >= io_tlb_start && paddr < io_tlb_end;
 }
 
+phys_addr_t swiotlb_get_orig_phys(phys_addr_t tlb_addr);
+
 bool swiotlb_map(struct device *dev, phys_addr_t *phys, dma_addr_t *dma_addr,
 		size_t size, enum dma_data_direction dir, unsigned long attrs);
 void __init swiotlb_exit(void);
@@ -85,6 +87,11 @@ static inline bool is_swiotlb_buffer(phys_addr_t paddr)
 {
 	return false;
 }
+
+static inline phys_addr_t swiotlb_get_orig_phys(phys_addr_t tlb_addr)
+{
+	return PHYS_ADDR_MAX;
+}
 static inline bool swiotlb_map(struct device *dev, phys_addr_t *phys,
 		dma_addr_t *dma_addr, size_t size, enum dma_data_direction dir,
 		unsigned long attrs)
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index 2b6f245c9bb1..1a2d02727271 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -14,6 +14,7 @@
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/swiotlb.h>
 
 /*
  * Managed DMA API
@@ -352,10 +353,18 @@ dma_unmap_page_attrs_desc(struct device *dev, dma_addr_t addr, size_t size,
 	const struct dma_map_ops *ops = get_dma_ops(dev);
 	void *ptr = NULL;
 
-	if (dma_is_direct(ops))
-		ptr = phys_to_virt(dma_to_phys(dev, addr));
-	else if (ops && ops->get_virt_addr)
+	if (dma_is_direct(ops)) {
+		phys_addr_t phys = dma_to_phys(dev, addr);
+
+		if (is_swiotlb_buffer(phys)) {
+			phys = swiotlb_get_orig_phys(phys);
+			ptr = phys == PHYS_ADDR_MAX ? NULL : phys_to_virt(phys);
+		} else {
+			ptr = phys_to_virt(phys);
+		}
+	} else if (ops && ops->get_virt_addr) {
 		ptr = ops->get_virt_addr(dev, addr);
+	}
 
 	dma_unmap_page_attrs(dev, addr, size, dir, attrs);
 
@@ -370,10 +379,18 @@ void *dma_unmap_single_attrs_desc(struct device *dev, dma_addr_t addr,
 	const struct dma_map_ops *ops = get_dma_ops(dev);
 	void *ptr = NULL;
 
-	if (dma_is_direct(ops))
-		ptr = phys_to_virt(dma_to_phys(dev, addr));
-	else if (ops && ops->get_virt_addr)
+	if (dma_is_direct(ops)) {
+		phys_addr_t phys = dma_to_phys(dev, addr);
+
+		if (is_swiotlb_buffer(phys)) {
+			phys = swiotlb_get_orig_phys(phys);
+			ptr = phys == PHYS_ADDR_MAX ? NULL : phys_to_virt(phys);
+		} else {
+			ptr = phys_to_virt(phys);
+		}
+	} else if (ops && ops->get_virt_addr) {
 		ptr = ops->get_virt_addr(dev, addr);
+	}
 
 	dma_unmap_single_attrs(dev, addr, size, dir, attrs);
 
@@ -387,10 +404,18 @@ void *dma_sync_single_for_cpu_desc(struct device *dev, dma_addr_t addr,
 	const struct dma_map_ops *ops = get_dma_ops(dev);
 	void *ptr = NULL;
 
-	if (dma_is_direct(ops))
-		ptr = phys_to_virt(dma_to_phys(dev, addr));
-	else if (ops && ops->get_virt_addr)
+	if (dma_is_direct(ops)) {
+		phys_addr_t phys = dma_to_phys(dev, addr);
+
+		if (is_swiotlb_buffer(phys)) {
+			phys = swiotlb_get_orig_phys(phys);
+			ptr = phys == PHYS_ADDR_MAX ? NULL : phys_to_virt(phys);
+		} else {
+			ptr = phys_to_virt(phys);
+		}
+	} else if (ops && ops->get_virt_addr) {
 		ptr = ops->get_virt_addr(dev, addr);
+	}
 
 	dma_sync_single_for_cpu(dev, addr, size, dir);
 
diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index 673a2cdb2656..9b241cc0535b 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -701,6 +701,14 @@ bool is_swiotlb_active(void)
 	return io_tlb_end != 0;
 }
 
+phys_addr_t swiotlb_get_orig_phys(phys_addr_t tlb_addr)
+{
+	int index = (tlb_addr - io_tlb_start) >> IO_TLB_SHIFT;
+	phys_addr_t phys = io_tlb_orig_addr[index];
+
+	return phys == INVALID_PHYS_ADDR ? PHYS_ADDR_MAX : phys;
+}
+
 #ifdef CONFIG_DEBUG_FS
 
 static int __init swiotlb_create_debugfs(void)
-- 
2.17.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v3 4/4] dpaa2_eth: use new unmap and sync dma api variants
  2019-11-13 12:24 [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants Laurentiu Tudor
                   ` (2 preceding siblings ...)
  2019-11-13 12:24 ` [PATCH v3 3/4] swiotlb: make new {unmap,sync}_desc dma apis work with swiotlb Laurentiu Tudor
@ 2019-11-13 12:24 ` Laurentiu Tudor
  2019-11-13 20:11 ` [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants David Miller
  4 siblings, 0 replies; 10+ messages in thread
From: Laurentiu Tudor @ 2019-11-13 12:24 UTC (permalink / raw)
  To: hch, robin.murphy, joro, Ioana Ciocoi Radulescu, linux-kernel,
	iommu, netdev, Ioana Ciornei
  Cc: Leo Li, Diana Madalina Craciun, davem, Madalin Bucur,
	Camelia Alexandra Groza, Laurentiu Tudor

From: Laurentiu Tudor <laurentiu.tudor@nxp.com>

Convert this driver to usage of the newly introduced dma unmap and
sync DMA APIs. This will get rid of the unsupported direct usage of
iommu_iova_to_phys() API.

Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
---
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  | 43 ++++++++-----------
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.h  |  1 -
 2 files changed, 18 insertions(+), 26 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 19379bae0144..6b941b753106 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -29,16 +29,6 @@ MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Freescale Semiconductor, Inc");
 MODULE_DESCRIPTION("Freescale DPAA2 Ethernet Driver");
 
-static void *dpaa2_iova_to_virt(struct iommu_domain *domain,
-				dma_addr_t iova_addr)
-{
-	phys_addr_t phys_addr;
-
-	phys_addr = domain ? iommu_iova_to_phys(domain, iova_addr) : iova_addr;
-
-	return phys_to_virt(phys_addr);
-}
-
 static void validate_rx_csum(struct dpaa2_eth_priv *priv,
 			     u32 fd_status,
 			     struct sk_buff *skb)
@@ -85,9 +75,9 @@ static void free_rx_fd(struct dpaa2_eth_priv *priv,
 	sgt = vaddr + dpaa2_fd_get_offset(fd);
 	for (i = 1; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) {
 		addr = dpaa2_sg_get_addr(&sgt[i]);
-		sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
-		dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
-			       DMA_BIDIRECTIONAL);
+		sg_vaddr = dma_unmap_single_desc(dev, addr,
+						 DPAA2_ETH_RX_BUF_SIZE,
+						 DMA_BIDIRECTIONAL);
 
 		free_pages((unsigned long)sg_vaddr, 0);
 		if (dpaa2_sg_is_final(&sgt[i]))
@@ -143,9 +133,9 @@ static struct sk_buff *build_frag_skb(struct dpaa2_eth_priv *priv,
 
 		/* Get the address and length from the S/G entry */
 		sg_addr = dpaa2_sg_get_addr(sge);
-		sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, sg_addr);
-		dma_unmap_page(dev, sg_addr, DPAA2_ETH_RX_BUF_SIZE,
-			       DMA_BIDIRECTIONAL);
+		sg_vaddr = dma_unmap_single_desc(dev, sg_addr,
+						 DPAA2_ETH_RX_BUF_SIZE,
+						 DMA_BIDIRECTIONAL);
 
 		sg_length = dpaa2_sg_get_len(sge);
 
@@ -210,9 +200,9 @@ static void free_bufs(struct dpaa2_eth_priv *priv, u64 *buf_array, int count)
 	int i;
 
 	for (i = 0; i < count; i++) {
-		vaddr = dpaa2_iova_to_virt(priv->iommu_domain, buf_array[i]);
-		dma_unmap_page(dev, buf_array[i], DPAA2_ETH_RX_BUF_SIZE,
-			       DMA_BIDIRECTIONAL);
+		vaddr = dma_unmap_single_desc(dev, buf_array[i],
+					      DPAA2_ETH_RX_BUF_SIZE,
+					      DMA_BIDIRECTIONAL);
 		free_pages((unsigned long)vaddr, 0);
 	}
 }
@@ -369,9 +359,8 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
 	/* Tracing point */
 	trace_dpaa2_rx_fd(priv->net_dev, fd);
 
-	vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
-	dma_sync_single_for_cpu(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
-				DMA_BIDIRECTIONAL);
+	vaddr = dma_sync_single_for_cpu_desc(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
+					     DMA_BIDIRECTIONAL);
 
 	fas = dpaa2_get_fas(vaddr, false);
 	prefetch(fas);
@@ -682,7 +671,8 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
 	u32 fd_len = dpaa2_fd_get_len(fd);
 
 	fd_addr = dpaa2_fd_get_addr(fd);
-	buffer_start = dpaa2_iova_to_virt(priv->iommu_domain, fd_addr);
+	buffer_start = dma_sync_single_for_cpu_desc(dev, fd_addr, sizeof(*swa),
+						    DMA_BIDIRECTIONAL);
 	swa = (struct dpaa2_eth_swa *)buffer_start;
 
 	if (fd_format == dpaa2_fd_single) {
@@ -3435,6 +3425,11 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
 
 	dev = &dpni_dev->dev;
 
+	if (!dma_can_unmap_by_dma_addr(dev)) {
+		dev_err(dev, "required dma unmap/sync APIs not available\n");
+		return -ENOTSUPP;
+	}
+
 	/* Net device */
 	net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA2_ETH_MAX_NETDEV_QUEUES);
 	if (!net_dev) {
@@ -3448,8 +3443,6 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
 	priv = netdev_priv(net_dev);
 	priv->net_dev = net_dev;
 
-	priv->iommu_domain = iommu_get_domain_for_dev(dev);
-
 	/* Obtain a MC portal */
 	err = fsl_mc_portal_allocate(dpni_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
 				     &priv->mc_io);
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
index 8a0e65b3267f..4e5183617ebd 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
@@ -374,7 +374,6 @@ struct dpaa2_eth_priv {
 
 	struct fsl_mc_device *dpbp_dev;
 	u16 bpid;
-	struct iommu_domain *iommu_domain;
 
 	bool tx_tstamp; /* Tx timestamping enabled */
 	bool rx_tstamp; /* Rx timestamping enabled */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants
  2019-11-13 12:24 [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants Laurentiu Tudor
                   ` (3 preceding siblings ...)
  2019-11-13 12:24 ` [PATCH v3 4/4] dpaa2_eth: use new unmap and sync dma api variants Laurentiu Tudor
@ 2019-11-13 20:11 ` David Miller
  2019-11-14 11:13   ` Laurentiu Tudor
  2019-11-21  7:41   ` Christoph Hellwig
  4 siblings, 2 replies; 10+ messages in thread
From: David Miller @ 2019-11-13 20:11 UTC (permalink / raw)
  To: laurentiu.tudor
  Cc: hch, robin.murphy, joro, ruxandra.radulescu, linux-kernel, iommu,
	netdev, ioana.ciornei, leoyang.li, diana.craciun, madalin.bucur,
	camelia.groza

From: Laurentiu Tudor <laurentiu.tudor@nxp.com>
Date: Wed, 13 Nov 2019 12:24:17 +0000

> From: Laurentiu Tudor <laurentiu.tudor@nxp.com>
> 
> This series introduces a few new dma unmap and sync api variants that,
> on top of what the originals do, return the virtual address
> corresponding to the input dma address. In order to do that a new dma
> map op is added, .get_virt_addr that takes the input dma address and
> returns the virtual address backing it up.
> The second patch adds an implementation for this new dma map op in the
> generic iommu dma glue code and wires it in.
> The third patch updates the dpaa2-eth driver to use the new apis.

The driver should store the mapping in it's private software state if
it needs this kind of conversion.

This is huge precendence for this, and there is therefore no need to
add even more complication and methods and burdon to architecture code
for the sake of this.

Thank you.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants
  2019-11-13 20:11 ` [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants David Miller
@ 2019-11-14 11:13   ` Laurentiu Tudor
  2019-11-19 14:09     ` Ioana Ciornei
  2019-11-21  7:41   ` Christoph Hellwig
  1 sibling, 1 reply; 10+ messages in thread
From: Laurentiu Tudor @ 2019-11-14 11:13 UTC (permalink / raw)
  To: David Miller
  Cc: hch, robin.murphy, joro, Ioana Ciocoi Radulescu, linux-kernel,
	iommu, netdev, Ioana Ciornei, Leo Li, Diana Madalina Craciun,
	Madalin Bucur, Camelia Alexandra Groza, Roy Pledge

On 13.11.2019 22:11, David Miller wrote:
> From: Laurentiu Tudor <laurentiu.tudor@nxp.com>
> Date: Wed, 13 Nov 2019 12:24:17 +0000
> 
>> From: Laurentiu Tudor <laurentiu.tudor@nxp.com>
>>
>> This series introduces a few new dma unmap and sync api variants that,
>> on top of what the originals do, return the virtual address
>> corresponding to the input dma address. In order to do that a new dma
>> map op is added, .get_virt_addr that takes the input dma address and
>> returns the virtual address backing it up.
>> The second patch adds an implementation for this new dma map op in the
>> generic iommu dma glue code and wires it in.
>> The third patch updates the dpaa2-eth driver to use the new apis.
> 
> The driver should store the mapping in it's private software state if
> it needs this kind of conversion.

On this hardware there's no way of conveying additional frame 
information, such as original va/pa behind the dma address. We have also 
pondered on the idea of keeping this in some kind of data structure but 
could not find a lock-less solution which obviously would bring 
performance to the ground.
I'll let my colleagues maintaining these ethernet drivers to get into 
more details, if required.

---
Best Regards, Laurentiu

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants
  2019-11-14 11:13   ` Laurentiu Tudor
@ 2019-11-19 14:09     ` Ioana Ciornei
  0 siblings, 0 replies; 10+ messages in thread
From: Ioana Ciornei @ 2019-11-19 14:09 UTC (permalink / raw)
  To: Laurentiu Tudor, David Miller
  Cc: hch, robin.murphy, joro, Ioana Ciocoi Radulescu, linux-kernel,
	iommu, netdev, Leo Li, Diana Madalina Craciun, Madalin Bucur,
	Camelia Alexandra Groza, Roy Pledge

> Subject: Re: [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync
> variants
> 
> On 13.11.2019 22:11, David Miller wrote:
> > From: Laurentiu Tudor <laurentiu.tudor@nxp.com>
> > Date: Wed, 13 Nov 2019 12:24:17 +0000
> >
> >> From: Laurentiu Tudor <laurentiu.tudor@nxp.com>
> >>
> >> This series introduces a few new dma unmap and sync api variants
> >> that, on top of what the originals do, return the virtual address
> >> corresponding to the input dma address. In order to do that a new dma
> >> map op is added, .get_virt_addr that takes the input dma address and
> >> returns the virtual address backing it up.
> >> The second patch adds an implementation for this new dma map op in
> >> the generic iommu dma glue code and wires it in.
> >> The third patch updates the dpaa2-eth driver to use the new apis.
> >
> > The driver should store the mapping in it's private software state if
> > it needs this kind of conversion.
> 
> On this hardware there's no way of conveying additional frame information,
> such as original va/pa behind the dma address. We have also pondered on the
> idea of keeping this in some kind of data structure but could not find a lock-less
> solution which obviously would bring performance to the ground.
> I'll let my colleagues maintaining these ethernet drivers to get into more details,
> if required.
> 

As Laurentiu pointed out before, keeping a mapping in the driver's private data doesn't
seem feasible without a locking mechanism which in turn would be an immense impact
performance wise.

We also feel that instead of hacking our individual drivers we should extend the
core DMA API to also fit this use case, which is exactly what
Laurentiu's patch set is doing.

Our hope is to come to a common understanding of the next steps since this
would unblock some activities currently in the backlog.

Ioana

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants
  2019-11-13 20:11 ` [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants David Miller
  2019-11-14 11:13   ` Laurentiu Tudor
@ 2019-11-21  7:41   ` Christoph Hellwig
  2019-12-02 14:58     ` Madalin Bucur
  1 sibling, 1 reply; 10+ messages in thread
From: Christoph Hellwig @ 2019-11-21  7:41 UTC (permalink / raw)
  To: David Miller
  Cc: laurentiu.tudor, hch, robin.murphy, joro, ruxandra.radulescu,
	linux-kernel, iommu, netdev, ioana.ciornei, leoyang.li,
	diana.craciun, madalin.bucur, camelia.groza

On Wed, Nov 13, 2019 at 12:11:32PM -0800, David Miller wrote:
> > This series introduces a few new dma unmap and sync api variants that,
> > on top of what the originals do, return the virtual address
> > corresponding to the input dma address. In order to do that a new dma
> > map op is added, .get_virt_addr that takes the input dma address and
> > returns the virtual address backing it up.
> > The second patch adds an implementation for this new dma map op in the
> > generic iommu dma glue code and wires it in.
> > The third patch updates the dpaa2-eth driver to use the new apis.
> 
> The driver should store the mapping in it's private software state if
> it needs this kind of conversion.

I think the problem for this driver (and a few others) is that they
somehow manage to split I/O completions at a different boundary
than submissions.  For me with my block I/O background this seems
weird, but I'll need networking folks to double check the theory.

> This is huge precendence for this, and there is therefore no need to
> add even more complication and methods and burdon to architecture code
> for the sake of this.

Unfortunately there are various drivers that abuse iommu_iova_to_phys
to get a struct page to unmap.  Two of theose are network drivers
that went in through you (dpaa2 and thunder), additonally the 
caam crypto driver (which I think is the same SOC family as dpaa,
but I'm not sure) and the AMD GPU driver.

We also have drivers that just don't unmap and this don't work with
iommus or dma-debug (IBM EMAC another net driver).

That being said I hate these new API, but I still think they are less
bad than these IOMMU API abuses people do now.  If experienced
networking folks know a way to get rid of both I'm all for it.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants
  2019-11-21  7:41   ` Christoph Hellwig
@ 2019-12-02 14:58     ` Madalin Bucur
  0 siblings, 0 replies; 10+ messages in thread
From: Madalin Bucur @ 2019-12-02 14:58 UTC (permalink / raw)
  To: Christoph Hellwig, David Miller
  Cc: Laurentiu Tudor, robin.murphy, joro, Ioana Ciocoi Radulescu,
	linux-kernel, iommu, netdev, Ioana Ciornei, Leo Li,
	Diana Madalina Craciun, Camelia Alexandra Groza

> -----Original Message-----
> From: Christoph Hellwig <hch@lst.de>
> To: David Miller <davem@davemloft.net>
> Subject: Re: [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync
> variants
> 
> On Wed, Nov 13, 2019 at 12:11:32PM -0800, David Miller wrote:
> > > This series introduces a few new dma unmap and sync api variants
> that,
> > > on top of what the originals do, return the virtual address
> > > corresponding to the input dma address. In order to do that a new dma
> > > map op is added, .get_virt_addr that takes the input dma address and
> > > returns the virtual address backing it up.
> > > The second patch adds an implementation for this new dma map op in
> the
> > > generic iommu dma glue code and wires it in.
> > > The third patch updates the dpaa2-eth driver to use the new apis.
> >
> > The driver should store the mapping in it's private software state if
> > it needs this kind of conversion.
> 
> I think the problem for this driver (and a few others) is that they
> somehow manage to split I/O completions at a different boundary
> than submissions.  For me with my block I/O background this seems
> weird, but I'll need networking folks to double check the theory.
> 
> > This is huge precendence for this, and there is therefore no need to
> > add even more complication and methods and burdon to architecture code
> > for the sake of this.
> 
> Unfortunately there are various drivers that abuse iommu_iova_to_phys
> to get a struct page to unmap.  Two of theose are network drivers
> that went in through you (dpaa2 and thunder), additonally the
> caam crypto driver (which I think is the same SOC family as dpaa,
> but I'm not sure) and the AMD GPU driver.
> 
> We also have drivers that just don't unmap and this don't work with
> iommus or dma-debug (IBM EMAC another net driver).
> 
> That being said I hate these new API, but I still think they are less
> bad than these IOMMU API abuses people do now.  If experienced
> networking folks know a way to get rid of both I'm all for it.

Hi,

will this API be included during the v5.5 kernel development cycle or is
there an alternative solution?

Thank you,
Madalin

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, back to index

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-13 12:24 [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants Laurentiu Tudor
2019-11-13 12:24 ` [PATCH v3 1/4] dma-mapping: introduce new dma unmap and sync api variants Laurentiu Tudor
2019-11-13 12:24 ` [PATCH v3 2/4] iommu/dma: wire-up new dma map op .get_virt_addr Laurentiu Tudor
2019-11-13 12:24 ` [PATCH v3 3/4] swiotlb: make new {unmap,sync}_desc dma apis work with swiotlb Laurentiu Tudor
2019-11-13 12:24 ` [PATCH v3 4/4] dpaa2_eth: use new unmap and sync dma api variants Laurentiu Tudor
2019-11-13 20:11 ` [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants David Miller
2019-11-14 11:13   ` Laurentiu Tudor
2019-11-19 14:09     ` Ioana Ciornei
2019-11-21  7:41   ` Christoph Hellwig
2019-12-02 14:58     ` Madalin Bucur

Netdev Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/netdev/0 netdev/git/0.git
	git clone --mirror https://lore.kernel.org/netdev/1 netdev/git/1.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 netdev netdev/ https://lore.kernel.org/netdev \
		netdev@vger.kernel.org
	public-inbox-index netdev

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.netdev


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git