public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] MIPS: Use dma-mapping-common.h and use swiotlb for Octeon.
@ 2010-09-23 22:38 David Daney
  2010-09-23 22:38 ` [PATCH 1/9] MIPS: Octeon: Set dma_masks for octeon_mgmt device David Daney
                   ` (8 more replies)
  0 siblings, 9 replies; 21+ messages in thread
From: David Daney @ 2010-09-23 22:38 UTC (permalink / raw)
  To: linux-mips, ralf, linux-kernel; +Cc: David Daney

The Octeon family of SOCs support physical memory outside of the
32-bit addressing range.  To support 32-bit devices, we need to use
the swiotlb bounce buffer mechanism.

There are several parts to the patch set.

1 -     Set the proper dma_masks for the octeon_mgmt platform device so
        that it continues to function with the rewritten dma mapping
        code to follow.

2,3,4 - Establish a properly constrained DMA32 zone for Octeon.

5 -     Convert MIPS to use dma-mapping-common.h

6,7 -   Trivial swiotlb changes.

8 -     Get MIPS ready to use swiotlb.

9 -     Rewrite Octeon dma mapping code.

Since the only non-MIPS parts of this patch set are trivial changes to
swiotlb, I would suggest that they could all be merged via Ralf's tree
if deemed acceptable.

David Daney (9):
  MIPS: Octeon: Set dma_masks for octeon_mgmt device.
  MIPS: Allow MAX_DMA32_PFN to be overridden.
  MIPS: Octeon: Adjust top of DMA32 zone.
  MIPS: Octeon: Select ZONE_DMA32
  MIPS: Convert DMA to use dma-mapping-common.h
  swiotlb: Declare swiotlb_init_with_default_size()
  swiotlb: Make bounce buffer bounds non-static.
  MIPS: Add a platform hook for swiotlb setup.
  MIPS: Octeon: Rewrite DMA mapping functions.

 arch/mips/Kconfig                                  |    3 +
 arch/mips/cavium-octeon/Kconfig                    |   12 +
 arch/mips/cavium-octeon/dma-octeon.c               |  529 +++++++++-----------
 arch/mips/cavium-octeon/octeon-platform.c          |    5 +
 arch/mips/include/asm/bootinfo.h                   |    5 +
 arch/mips/include/asm/device.h                     |   15 +-
 arch/mips/include/asm/dma-mapping.h                |  125 ++++--
 arch/mips/include/asm/dma.h                        |    3 +
 .../asm/mach-cavium-octeon/cpu-feature-overrides.h |    6 +
 .../include/asm/mach-cavium-octeon/dma-coherence.h |   19 +-
 arch/mips/include/asm/octeon/pci-octeon.h          |   10 +
 arch/mips/kernel/setup.c                           |    5 +
 arch/mips/mm/dma-default.c                         |  179 +++----
 arch/mips/pci/pci-octeon.c                         |   60 ++-
 arch/mips/pci/pcie-octeon.c                        |    5 +
 include/linux/swiotlb.h                            |    7 +
 lib/swiotlb.c                                      |   62 ++--
 17 files changed, 571 insertions(+), 479 deletions(-)

-- 
1.7.2.2


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

* [PATCH 1/9] MIPS: Octeon: Set dma_masks for octeon_mgmt device.
  2010-09-23 22:38 [PATCH 0/9] MIPS: Use dma-mapping-common.h and use swiotlb for Octeon David Daney
@ 2010-09-23 22:38 ` David Daney
  2010-09-23 22:38 ` [PATCH 2/9] MIPS: Allow MAX_DMA32_PFN to be overridden David Daney
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: David Daney @ 2010-09-23 22:38 UTC (permalink / raw)
  To: linux-mips, ralf, linux-kernel; +Cc: David Daney

This allows follow-on patches to dma mapping functions to work with
the octeon mgmt device..

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
 arch/mips/cavium-octeon/octeon-platform.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index 62ac30e..c32d40d 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -10,6 +10,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/i2c.h>
+#include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
@@ -301,6 +302,10 @@ static int __init octeon_mgmt_device_init(void)
 			ret = -ENOMEM;
 			goto out;
 		}
+		/* No DMA restrictions */
+		pd->dev.coherent_dma_mask = DMA_BIT_MASK(64);
+		pd->dev.dma_mask = &pd->dev.coherent_dma_mask;
+
 		switch (port) {
 		case 0:
 			mgmt_port_resource.start = OCTEON_IRQ_MII0;
-- 
1.7.2.2


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

* [PATCH 2/9] MIPS: Allow MAX_DMA32_PFN to be overridden.
  2010-09-23 22:38 [PATCH 0/9] MIPS: Use dma-mapping-common.h and use swiotlb for Octeon David Daney
  2010-09-23 22:38 ` [PATCH 1/9] MIPS: Octeon: Set dma_masks for octeon_mgmt device David Daney
@ 2010-09-23 22:38 ` David Daney
  2010-09-23 22:38 ` [PATCH 3/9] MIPS: Octeon: Adjust top of DMA32 zone David Daney
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: David Daney @ 2010-09-23 22:38 UTC (permalink / raw)
  To: linux-mips, ralf, linux-kernel; +Cc: David Daney

DMA mapping may reduce the usable physical address range usable for
32-bit DMA.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
 arch/mips/include/asm/dma.h |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/mips/include/asm/dma.h b/arch/mips/include/asm/dma.h
index 1353c81..2d47da6 100644
--- a/arch/mips/include/asm/dma.h
+++ b/arch/mips/include/asm/dma.h
@@ -91,7 +91,10 @@
 #define MAX_DMA_ADDRESS		(PAGE_OFFSET + 0x01000000)
 #endif
 #define MAX_DMA_PFN		PFN_DOWN(virt_to_phys((void *)MAX_DMA_ADDRESS))
+
+#ifndef MAX_DMA32_PFN
 #define MAX_DMA32_PFN		(1UL << (32 - PAGE_SHIFT))
+#endif
 
 /* 8237 DMA controllers */
 #define IO_DMA1_BASE	0x00	/* 8 bit slave DMA, channels 0..3 */
-- 
1.7.2.2


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

* [PATCH 3/9] MIPS: Octeon: Adjust top of DMA32 zone.
  2010-09-23 22:38 [PATCH 0/9] MIPS: Use dma-mapping-common.h and use swiotlb for Octeon David Daney
  2010-09-23 22:38 ` [PATCH 1/9] MIPS: Octeon: Set dma_masks for octeon_mgmt device David Daney
  2010-09-23 22:38 ` [PATCH 2/9] MIPS: Allow MAX_DMA32_PFN to be overridden David Daney
@ 2010-09-23 22:38 ` David Daney
  2010-09-23 22:38 ` [PATCH 4/9] MIPS: Octeon: Select ZONE_DMA32 David Daney
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: David Daney @ 2010-09-23 22:38 UTC (permalink / raw)
  To: linux-mips, ralf, linux-kernel; +Cc: David Daney

On OCTEON, we reserve the last 256MB of 32-bit PCI address space,
mapping the RAM in this region at a high DMA address.  This makes
memory in this region unavailable for 32-bit DMA.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
 .../asm/mach-cavium-octeon/cpu-feature-overrides.h |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h
index b952fc7..c84ed74 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h
@@ -81,4 +81,10 @@ static inline int octeon_has_saa(void)
 	return id >= 0x000d0300;
 }
 
+/*
+ * The last 256MB are reserved for device to device mappings and the
+ * BAR1 hole.
+ */
+#define MAX_DMA32_PFN (((1ULL << 32) - (1ULL << 28)) >> PAGE_SHIFT)
+
 #endif
-- 
1.7.2.2


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

* [PATCH 4/9] MIPS: Octeon: Select ZONE_DMA32
  2010-09-23 22:38 [PATCH 0/9] MIPS: Use dma-mapping-common.h and use swiotlb for Octeon David Daney
                   ` (2 preceding siblings ...)
  2010-09-23 22:38 ` [PATCH 3/9] MIPS: Octeon: Adjust top of DMA32 zone David Daney
@ 2010-09-23 22:38 ` David Daney
  2010-09-23 22:38 ` [PATCH 5/9] MIPS: Convert DMA to use dma-mapping-common.h David Daney
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: David Daney @ 2010-09-23 22:38 UTC (permalink / raw)
  To: linux-mips, ralf, linux-kernel; +Cc: David Daney

Give us a nice place to allocate coherent DMA memory for 32-bit
devices.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
 arch/mips/Kconfig |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 5526faa..6c33709 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -693,6 +693,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD
 	select SWAP_IO_SPACE
 	select HW_HAS_PCI
 	select ARCH_SUPPORTS_MSI
+	select ZONE_DMA32
 	help
 	  This option supports all of the Octeon reference boards from Cavium
 	  Networks. It builds a kernel that dynamically determines the Octeon
-- 
1.7.2.2


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

* [PATCH 5/9] MIPS: Convert DMA to use dma-mapping-common.h
  2010-09-23 22:38 [PATCH 0/9] MIPS: Use dma-mapping-common.h and use swiotlb for Octeon David Daney
                   ` (3 preceding siblings ...)
  2010-09-23 22:38 ` [PATCH 4/9] MIPS: Octeon: Select ZONE_DMA32 David Daney
@ 2010-09-23 22:38 ` David Daney
  2010-09-24  1:03   ` [PATCH] MIPS: Remove plat_map_dma_mem_page() David Daney
  2010-09-27  5:30   ` [PATCH 5/9] MIPS: Convert DMA to use dma-mapping-common.h FUJITA Tomonori
  2010-09-23 22:38 ` [PATCH 8/9] MIPS: Add a platform hook for swiotlb setup David Daney
                   ` (3 subsequent siblings)
  8 siblings, 2 replies; 21+ messages in thread
From: David Daney @ 2010-09-23 22:38 UTC (permalink / raw)
  To: linux-mips, ralf, linux-kernel; +Cc: David Daney

Use asm-generic/dma-mapping-common.h to handle all DMA mapping
operations and establish a default get_dma_ops() that forwards all
operations to the existing code.

Augment dev_archdata to carry a pointer to the struct dma_map_ops,
allowing DMA operations to be overridden on a per device basis.
Currently this is never filled in, so the default dma_map_ops are
used.  A follow-on patch sets this for Octeon PCI devices.

Also initialize the dma_debug system as it is now used if it is
configured.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
 arch/mips/Kconfig                   |    2 +
 arch/mips/include/asm/device.h      |   15 +++-
 arch/mips/include/asm/dma-mapping.h |  125 +++++++++++++++++--------
 arch/mips/mm/dma-default.c          |  179 +++++++++++++---------------------
 4 files changed, 172 insertions(+), 149 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 6c33709..e68b89f 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -14,6 +14,8 @@ config MIPS
 	select HAVE_KRETPROBES
 	select RTC_LIB if !MACH_LOONGSON
 	select GENERIC_ATOMIC64 if !64BIT
+	select HAVE_DMA_ATTRS
+	select HAVE_DMA_API_DEBUG
 
 mainmenu "Linux/MIPS Kernel Configuration"
 
diff --git a/arch/mips/include/asm/device.h b/arch/mips/include/asm/device.h
index 06746c5..65bf274 100644
--- a/arch/mips/include/asm/device.h
+++ b/arch/mips/include/asm/device.h
@@ -3,4 +3,17 @@
  *
  * This file is released under the GPLv2
  */
-#include <asm-generic/device.h>
+#ifndef _ASM_MIPS_DEVICE_H
+#define _ASM_MIPS_DEVICE_H
+
+struct mips_dma_map_ops;
+
+struct dev_archdata {
+	/* DMA operations on that device */
+	struct mips_dma_map_ops	*dma_ops;
+};
+
+struct pdev_archdata {
+};
+
+#endif /* _ASM_MIPS_DEVICE_H*/
diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h
index 18fbf7a..9a4c307 100644
--- a/arch/mips/include/asm/dma-mapping.h
+++ b/arch/mips/include/asm/dma-mapping.h
@@ -5,51 +5,67 @@
 #include <asm/cache.h>
 #include <asm-generic/dma-coherent.h>
 
-void *dma_alloc_noncoherent(struct device *dev, size_t size,
-			   dma_addr_t *dma_handle, gfp_t flag);
+struct mips_dma_map_ops {
+	struct dma_map_ops dma_map_ops;
+	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);
+};
 
-void dma_free_noncoherent(struct device *dev, size_t size,
-			 void *vaddr, dma_addr_t dma_handle);
+extern struct mips_dma_map_ops *mips_dma_map_ops;
 
-void *dma_alloc_coherent(struct device *dev, size_t size,
-			   dma_addr_t *dma_handle, gfp_t flag);
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+	struct mips_dma_map_ops *ops;
 
-void dma_free_coherent(struct device *dev, size_t size,
-			 void *vaddr, dma_addr_t dma_handle);
+	if (dev && dev->archdata.dma_ops)
+		ops = dev->archdata.dma_ops;
+	else
+		ops = mips_dma_map_ops;
+
+	return &ops->dma_map_ops;
+}
+
+static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+	struct mips_dma_map_ops *ops = container_of(get_dma_ops(dev),
+						    struct mips_dma_map_ops,
+						    dma_map_ops);
+
+	return ops->phys_to_dma(dev, paddr);
+}
+
+static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+	struct mips_dma_map_ops *ops = container_of(get_dma_ops(dev),
+						    struct mips_dma_map_ops,
+						    dma_map_ops);
+
+	return ops->dma_to_phys(dev, daddr);
+}
+
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+	if (!dev->dma_mask)
+		return 0;
+
+	return addr + size <= *dev->dma_mask;
+}
+
+static inline void dma_mark_clean(void *addr, size_t size) {}
 
-extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
-	enum dma_data_direction direction);
-extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
-	size_t size, enum dma_data_direction direction);
-extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-	enum dma_data_direction direction);
-extern dma_addr_t dma_map_page(struct device *dev, struct page *page,
-	unsigned long offset, size_t size, enum dma_data_direction direction);
-
-static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
-	size_t size, enum dma_data_direction direction)
+#include <asm-generic/dma-mapping-common.h>
+
+static inline int dma_supported(struct device *dev, u64 mask)
 {
-	dma_unmap_single(dev, dma_address, size, direction);
+	struct dma_map_ops *ops = get_dma_ops(dev);
+	return ops->dma_supported(dev, mask);
 }
 
-extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
-	int nhwentries, enum dma_data_direction direction);
-extern void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
-	size_t size, enum dma_data_direction direction);
-extern void dma_sync_single_for_device(struct device *dev,
-	dma_addr_t dma_handle, size_t size, enum dma_data_direction direction);
-extern void dma_sync_single_range_for_cpu(struct device *dev,
-	dma_addr_t dma_handle, unsigned long offset, size_t size,
-	enum dma_data_direction direction);
-extern void dma_sync_single_range_for_device(struct device *dev,
-	dma_addr_t dma_handle, unsigned long offset, size_t size,
-	enum dma_data_direction direction);
-extern void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
-	int nelems, enum dma_data_direction direction);
-extern void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
-	int nelems, enum dma_data_direction direction);
-extern int dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
-extern int dma_supported(struct device *dev, u64 mask);
+static inline int dma_mapping_error(struct device *dev, u64 mask)
+{
+	struct dma_map_ops *ops = get_dma_ops(dev);
+	return ops->mapping_error(dev, mask);
+}
 
 static inline int
 dma_set_mask(struct device *dev, u64 mask)
@@ -65,4 +81,37 @@ dma_set_mask(struct device *dev, u64 mask)
 extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 	       enum dma_data_direction direction);
 
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+				       dma_addr_t *dma_handle, gfp_t gfp)
+{
+	void *ret;
+	struct dma_map_ops *ops = get_dma_ops(dev);
+
+	ret = ops->alloc_coherent(dev, size, dma_handle, gfp);
+
+	debug_dma_alloc_coherent(dev, size, *dma_handle, ret);
+
+	return ret;
+}
+
+static inline void dma_free_coherent(struct device *dev, size_t size,
+				     void *vaddr, dma_addr_t dma_handle)
+{
+	struct dma_map_ops *ops = get_dma_ops(dev);
+
+	ops->free_coherent(dev, size, vaddr, dma_handle);
+
+	debug_dma_free_coherent(dev, size, vaddr, dma_handle);
+}
+
+
+void *dma_alloc_noncoherent(struct device *dev, size_t size,
+			   dma_addr_t *dma_handle, gfp_t flag);
+
+void dma_free_noncoherent(struct device *dev, size_t size,
+			 void *vaddr, dma_addr_t dma_handle);
+
+dma_addr_t mips_unity_phys_to_dma(struct device *dev, phys_addr_t paddr);
+phys_addr_t mips_unity_dma_to_phys(struct device *dev, dma_addr_t daddr);
+
 #endif /* _ASM_DMA_MAPPING_H */
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 469d401..4aeae57 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -95,10 +95,9 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size,
 
 	return ret;
 }
-
 EXPORT_SYMBOL(dma_alloc_noncoherent);
 
-void *dma_alloc_coherent(struct device *dev, size_t size,
+static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
 	dma_addr_t * dma_handle, gfp_t gfp)
 {
 	void *ret;
@@ -123,7 +122,6 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
 	return ret;
 }
 
-EXPORT_SYMBOL(dma_alloc_coherent);
 
 void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
 	dma_addr_t dma_handle)
@@ -131,10 +129,9 @@ void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
 	plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL);
 	free_pages((unsigned long) vaddr, get_order(size));
 }
-
 EXPORT_SYMBOL(dma_free_noncoherent);
 
-void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
 	dma_addr_t dma_handle)
 {
 	unsigned long addr = (unsigned long) vaddr;
@@ -151,8 +148,6 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
 	free_pages(addr, get_order(size));
 }
 
-EXPORT_SYMBOL(dma_free_coherent);
-
 static inline void __dma_sync(unsigned long addr, size_t size,
 	enum dma_data_direction direction)
 {
@@ -174,21 +169,8 @@ static inline void __dma_sync(unsigned long addr, size_t size,
 	}
 }
 
-dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
-	enum dma_data_direction direction)
-{
-	unsigned long addr = (unsigned long) ptr;
-
-	if (!plat_device_is_coherent(dev))
-		__dma_sync(addr, size, direction);
-
-	return plat_map_dma_mem(dev, ptr, size);
-}
-
-EXPORT_SYMBOL(dma_map_single);
-
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-	enum dma_data_direction direction)
+static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
+	size_t size, enum dma_data_direction direction, struct dma_attrs *attrs)
 {
 	if (cpu_is_noncoherent_r10000(dev))
 		__dma_sync(dma_addr_to_virt(dev, dma_addr), size,
@@ -197,15 +179,11 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 	plat_unmap_dma_mem(dev, dma_addr, size, direction);
 }
 
-EXPORT_SYMBOL(dma_unmap_single);
-
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-	enum dma_data_direction direction)
+static int mips_dma_map_sg(struct device *dev, struct scatterlist *sg,
+	int nents, enum dma_data_direction direction, struct dma_attrs *attrs)
 {
 	int i;
 
-	BUG_ON(direction == DMA_NONE);
-
 	for (i = 0; i < nents; i++, sg++) {
 		unsigned long addr;
 
@@ -219,33 +197,27 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 	return nents;
 }
 
-EXPORT_SYMBOL(dma_map_sg);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
-	unsigned long offset, size_t size, enum dma_data_direction direction)
+static dma_addr_t mips_dma_map_page(struct device *dev, struct page *page,
+	unsigned long offset, size_t size, enum dma_data_direction direction,
+	struct dma_attrs *attrs)
 {
-	BUG_ON(direction == DMA_NONE);
+	unsigned long addr;
 
-	if (!plat_device_is_coherent(dev)) {
-		unsigned long addr;
+	addr = (unsigned long) page_address(page) + offset;
 
-		addr = (unsigned long) page_address(page) + offset;
+	if (!plat_device_is_coherent(dev))
 		__dma_sync(addr, size, direction);
-	}
 
-	return plat_map_dma_mem_page(dev, page) + offset;
+	return plat_map_dma_mem(dev, (void *)addr, size);
 }
 
-EXPORT_SYMBOL(dma_map_page);
-
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-	enum dma_data_direction direction)
+static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+	int nhwentries, enum dma_data_direction direction,
+	struct dma_attrs *attrs)
 {
 	unsigned long addr;
 	int i;
 
-	BUG_ON(direction == DMA_NONE);
-
 	for (i = 0; i < nhwentries; i++, sg++) {
 		if (!plat_device_is_coherent(dev) &&
 		    direction != DMA_TO_DEVICE) {
@@ -257,13 +229,9 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
 	}
 }
 
-EXPORT_SYMBOL(dma_unmap_sg);
-
-void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
-	size_t size, enum dma_data_direction direction)
+static void mips_dma_sync_single_for_cpu(struct device *dev,
+	dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
-
 	if (cpu_is_noncoherent_r10000(dev)) {
 		unsigned long addr;
 
@@ -272,13 +240,9 @@ void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
 	}
 }
 
-EXPORT_SYMBOL(dma_sync_single_for_cpu);
-
-void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
-	size_t size, enum dma_data_direction direction)
+static void mips_dma_sync_single_for_device(struct device *dev,
+	dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
-
 	plat_extra_sync_for_device(dev);
 	if (!plat_device_is_coherent(dev)) {
 		unsigned long addr;
@@ -288,46 +252,11 @@ void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
 	}
 }
 
-EXPORT_SYMBOL(dma_sync_single_for_device);
-
-void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
-	unsigned long offset, size_t size, enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-
-	if (cpu_is_noncoherent_r10000(dev)) {
-		unsigned long addr;
-
-		addr = dma_addr_to_virt(dev, dma_handle);
-		__dma_sync(addr + offset, size, direction);
-	}
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
-
-void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
-	unsigned long offset, size_t size, enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-
-	plat_extra_sync_for_device(dev);
-	if (!plat_device_is_coherent(dev)) {
-		unsigned long addr;
-
-		addr = dma_addr_to_virt(dev, dma_handle);
-		__dma_sync(addr + offset, size, direction);
-	}
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_device);
-
-void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
-	enum dma_data_direction direction)
+static void mips_dma_sync_sg_for_cpu(struct device *dev,
+	struct scatterlist *sg, int nelems, enum dma_data_direction direction)
 {
 	int i;
 
-	BUG_ON(direction == DMA_NONE);
-
 	/* Make sure that gcc doesn't leave the empty loop body.  */
 	for (i = 0; i < nelems; i++, sg++) {
 		if (cpu_is_noncoherent_r10000(dev))
@@ -336,15 +265,11 @@ void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
 	}
 }
 
-EXPORT_SYMBOL(dma_sync_sg_for_cpu);
-
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
-	enum dma_data_direction direction)
+static void mips_dma_sync_sg_for_device(struct device *dev,
+	struct scatterlist *sg, int nelems, enum dma_data_direction direction)
 {
 	int i;
 
-	BUG_ON(direction == DMA_NONE);
-
 	/* Make sure that gcc doesn't leave the empty loop body.  */
 	for (i = 0; i < nelems; i++, sg++) {
 		if (!plat_device_is_coherent(dev))
@@ -353,24 +278,18 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nele
 	}
 }
 
-EXPORT_SYMBOL(dma_sync_sg_for_device);
-
-int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+int mips_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
 	return plat_dma_mapping_error(dev, dma_addr);
 }
 
-EXPORT_SYMBOL(dma_mapping_error);
-
-int dma_supported(struct device *dev, u64 mask)
+int mips_dma_supported(struct device *dev, u64 mask)
 {
 	return plat_dma_supported(dev, mask);
 }
 
-EXPORT_SYMBOL(dma_supported);
-
-void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
-	       enum dma_data_direction direction)
+void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+			 enum dma_data_direction direction)
 {
 	BUG_ON(direction == DMA_NONE);
 
@@ -379,4 +298,44 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 		__dma_sync((unsigned long)vaddr, size, direction);
 }
 
-EXPORT_SYMBOL(dma_cache_sync);
+dma_addr_t mips_unity_phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+	return paddr;
+}
+
+phys_addr_t mips_unity_dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+	return daddr;
+}
+
+static struct mips_dma_map_ops mips_default_dma_map_ops = {
+	.dma_map_ops = {
+		.alloc_coherent = mips_dma_alloc_coherent,
+		.free_coherent = mips_dma_free_coherent,
+		.map_page = mips_dma_map_page,
+		.unmap_page = mips_dma_unmap_page,
+		.map_sg = mips_dma_map_sg,
+		.unmap_sg = mips_dma_unmap_sg,
+		.sync_single_for_cpu = mips_dma_sync_single_for_cpu,
+		.sync_single_for_device = mips_dma_sync_single_for_device,
+		.sync_sg_for_cpu = mips_dma_sync_sg_for_cpu,
+		.sync_sg_for_device = mips_dma_sync_sg_for_device,
+		.mapping_error = mips_dma_mapping_error,
+		.dma_supported = mips_dma_supported
+	},
+	.phys_to_dma = mips_unity_phys_to_dma,
+	.dma_to_phys = mips_unity_dma_to_phys
+};
+
+struct mips_dma_map_ops *mips_dma_map_ops = &mips_default_dma_map_ops;
+EXPORT_SYMBOL(mips_dma_map_ops);
+
+#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
+
+static int __init mips_dma_init(void)
+{
+	dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+
+	return 0;
+}
+fs_initcall(mips_dma_init);
-- 
1.7.2.2


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

* [PATCH 8/9] MIPS: Add a platform hook for swiotlb setup.
  2010-09-23 22:38 [PATCH 0/9] MIPS: Use dma-mapping-common.h and use swiotlb for Octeon David Daney
                   ` (4 preceding siblings ...)
  2010-09-23 22:38 ` [PATCH 5/9] MIPS: Convert DMA to use dma-mapping-common.h David Daney
@ 2010-09-23 22:38 ` David Daney
  2010-09-24 16:08   ` Sergei Shtylyov
  2010-09-23 22:38 ` [PATCH 9/9] MIPS: Octeon: Rewrite DMA mapping functions David Daney
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: David Daney @ 2010-09-23 22:38 UTC (permalink / raw)
  To: linux-mips, ralf, linux-kernel; +Cc: David Daney

This allows platforms that are using the swiotlb to initialize it.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
 arch/mips/include/asm/bootinfo.h |    5 +++++
 arch/mips/kernel/setup.c         |    5 +++++
 2 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
index 15a8ef0..b3cf989 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -125,4 +125,9 @@ extern unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3;
  */
 extern void plat_mem_setup(void);
 
+/*
+ * Optional platform hook to call swiotlb_setup().
+ */
+extern void plat_swiotlb_setup(void);
+
 #endif /* _ASM_BOOTINFO_H */
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 85aef3f..8b650da 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -488,6 +488,11 @@ static void __init arch_mem_init(char **cmdline_p)
 
 	bootmem_init();
 	sparse_init();
+
+#ifdef CONFIG_SWIOTLB
+	plat_swiotlb_setup();
+#endif
+
 	paging_init();
 }
 
-- 
1.7.2.2


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

* [PATCH 9/9] MIPS: Octeon: Rewrite DMA mapping functions.
  2010-09-23 22:38 [PATCH 0/9] MIPS: Use dma-mapping-common.h and use swiotlb for Octeon David Daney
                   ` (5 preceding siblings ...)
  2010-09-23 22:38 ` [PATCH 8/9] MIPS: Add a platform hook for swiotlb setup David Daney
@ 2010-09-23 22:38 ` David Daney
  2010-09-24  1:06   ` [PATCH] MIPS: Octeon: Remove plat_map_dma_mem_page() David Daney
  2010-09-23 22:47 ` [PATCH 6/9] swiotlb: Declare swiotlb_init_with_default_size() David Daney
  2010-09-23 22:47 ` [PATCH 7/9] swiotlb: Make bounce buffer bounds non-static David Daney
  8 siblings, 1 reply; 21+ messages in thread
From: David Daney @ 2010-09-23 22:38 UTC (permalink / raw)
  To: linux-mips, ralf, linux-kernel; +Cc: David Daney

All Octeon chips can support more than 4GB of RAM.  Also due to how
Octeon PCI is setup, even some configurations with less than 4GB of
RAM will have portions that are not accessible from 32-bit devices.

Enable the swiotlb code to handle the cases where a device cannot
directly do DMA.  This is a complete rewrite of the Octeon DMA mapping
code.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
 arch/mips/cavium-octeon/Kconfig                    |   12 +
 arch/mips/cavium-octeon/dma-octeon.c               |  529 +++++++++-----------
 .../include/asm/mach-cavium-octeon/dma-coherence.h |   19 +-
 arch/mips/include/asm/octeon/pci-octeon.h          |   10 +
 arch/mips/pci/pci-octeon.c                         |   60 ++-
 arch/mips/pci/pcie-octeon.c                        |    5 +
 6 files changed, 336 insertions(+), 299 deletions(-)

diff --git a/arch/mips/cavium-octeon/Kconfig b/arch/mips/cavium-octeon/Kconfig
index 47323ca..475156b 100644
--- a/arch/mips/cavium-octeon/Kconfig
+++ b/arch/mips/cavium-octeon/Kconfig
@@ -87,3 +87,15 @@ config ARCH_SPARSEMEM_ENABLE
 config CAVIUM_OCTEON_HELPER
 	def_bool y
 	depends on OCTEON_ETHERNET || PCI
+
+config IOMMU_HELPER
+	bool
+
+config NEED_SG_DMA_LENGTH
+	bool
+
+config SWIOTLB
+	def_bool y
+	depends on CPU_CAVIUM_OCTEON
+	select IOMMU_HELPER
+	select NEED_SG_DMA_LENGTH
diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c
index d22b5a2..b94730a 100644
--- a/arch/mips/cavium-octeon/dma-octeon.c
+++ b/arch/mips/cavium-octeon/dma-octeon.c
@@ -8,335 +8,296 @@
  * Copyright (C) 2005 Ilya A. Volynets-Evenbakh <ilya@total-knowledge.com>
  * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
  * IP32 changes by Ilya.
- * Cavium Networks: Create new dma setup for Cavium Networks Octeon based on
- * the kernels original.
+ * Copyright (C) 2010 Cavium Networks, Inc.
  */
 #include <linux/types.h>
 #include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/string.h>
+#include <linux/init.h>
 #include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
+#include <linux/swiotlb.h>
 #include <linux/scatterlist.h>
 
-#include <linux/cache.h>
-#include <linux/io.h>
+#include <asm/bootinfo.h>
 
 #include <asm/octeon/octeon.h>
-#include <asm/octeon/cvmx-npi-defs.h>
-#include <asm/octeon/cvmx-pci-defs.h>
 
 #include <dma-coherence.h>
 
 #ifdef CONFIG_PCI
 #include <asm/octeon/pci-octeon.h>
-#endif
+#include <asm/octeon/cvmx-npi-defs.h>
+#include <asm/octeon/cvmx-pci-defs.h>
 
-#define BAR2_PCI_ADDRESS 0x8000000000ul
+static dma_addr_t octeon_hole_phys_to_dma(phys_addr_t paddr)
+{
+	if (paddr >= CVMX_PCIE_BAR1_PHYS_BASE && paddr < (CVMX_PCIE_BAR1_PHYS_BASE + CVMX_PCIE_BAR1_PHYS_SIZE))
+		return paddr - CVMX_PCIE_BAR1_PHYS_BASE + CVMX_PCIE_BAR1_RC_BASE;
+	else
+		return paddr;
+}
 
-struct bar1_index_state {
-	int16_t ref_count;	/* Number of PCI mappings using this index */
-	uint16_t address_bits;	/* Upper bits of physical address. This is
-				   shifted 22 bits */
-};
+static phys_addr_t octeon_hole_dma_to_phys(dma_addr_t daddr)
+{
+	if (daddr >= CVMX_PCIE_BAR1_RC_BASE)
+		return daddr + CVMX_PCIE_BAR1_PHYS_BASE - CVMX_PCIE_BAR1_RC_BASE;
+	else
+		return daddr;
+}
 
-#ifdef CONFIG_PCI
-static DEFINE_RAW_SPINLOCK(bar1_lock);
-static struct bar1_index_state bar1_state[32];
-#endif
+static dma_addr_t octeon_gen1_phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+	if (paddr >= 0x410000000ull && paddr < 0x420000000ull)
+		paddr -= 0x400000000ull;
+	return octeon_hole_phys_to_dma(paddr);
+}
+
+static phys_addr_t octeon_gen1_dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+	daddr = octeon_hole_dma_to_phys(daddr);
+
+	if (daddr >= 0x10000000ull && daddr < 0x20000000ull)
+		daddr += 0x400000000ull;
+
+	return daddr;
+}
+
+static dma_addr_t octeon_big_phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+	if (paddr >= 0x410000000ull && paddr < 0x420000000ull)
+		paddr -= 0x400000000ull;
+
+	/* Anything in the BAR1 hole or above goes via BAR2 */
+	if (paddr >= 0xf0000000ull)
+		paddr = OCTEON_BAR2_PCI_ADDRESS + paddr;
+
+	return paddr;
+}
 
-dma_addr_t octeon_map_dma_mem(struct device *dev, void *ptr, size_t size)
+static phys_addr_t octeon_big_dma_to_phys(struct device *dev, dma_addr_t daddr)
 {
-#ifndef CONFIG_PCI
-	/* Without PCI/PCIe this function can be called for Octeon internal
-	   devices such as USB. These devices all support 64bit addressing */
+	if (daddr >= OCTEON_BAR2_PCI_ADDRESS)
+		daddr -= OCTEON_BAR2_PCI_ADDRESS;
+
+	if (daddr >= 0x10000000ull && daddr < 0x20000000ull)
+		daddr += 0x400000000ull;
+	return daddr;
+}
+
+static dma_addr_t octeon_small_phys_to_dma(struct device *dev,
+					   phys_addr_t paddr)
+{
+	if (paddr >= 0x410000000ull && paddr < 0x420000000ull)
+		paddr -= 0x400000000ull;
+
+	/* Anything not in the BAR1 range goes via BAR2 */
+	if (paddr >= octeon_bar1_pci_phys && paddr < octeon_bar1_pci_phys + 0x8000000ull)
+		paddr = paddr - octeon_bar1_pci_phys;
+	else
+		paddr = OCTEON_BAR2_PCI_ADDRESS + paddr;
+
+	return paddr;
+}
+
+static phys_addr_t octeon_small_dma_to_phys(struct device *dev,
+					    dma_addr_t daddr)
+{
+	if (daddr >= OCTEON_BAR2_PCI_ADDRESS)
+		daddr -= OCTEON_BAR2_PCI_ADDRESS;
+	else
+		daddr += octeon_bar1_pci_phys;
+
+	if (daddr >= 0x10000000ull && daddr < 0x20000000ull)
+		daddr += 0x400000000ull;
+	return daddr;
+}
+
+#endif /* CONFIG_PCI */
+
+static dma_addr_t octeon_dma_map_page(struct device *dev, struct page *page,
+	unsigned long offset, size_t size, enum dma_data_direction direction,
+	struct dma_attrs *attrs)
+{
+	dma_addr_t daddr = swiotlb_map_page(dev, page, offset, size,
+					    direction, attrs);
 	mb();
-	return virt_to_phys(ptr);
-#else
-	unsigned long flags;
-	uint64_t dma_mask;
-	int64_t start_index;
-	dma_addr_t result = -1;
-	uint64_t physical = virt_to_phys(ptr);
-	int64_t index;
 
+	return daddr;
+}
+
+static int octeon_dma_map_sg(struct device *dev, struct scatterlist *sg,
+	int nents, enum dma_data_direction direction, struct dma_attrs *attrs)
+{
+	int r = swiotlb_map_sg_attrs(dev, sg, nents, direction, attrs);
 	mb();
-	/*
-	 * Use the DMA masks to determine the allowed memory
-	 * region. For us it doesn't limit the actual memory, just the
-	 * address visible over PCI.  Devices with limits need to use
-	 * lower indexed Bar1 entries.
-	 */
-	if (dev) {
-		dma_mask = dev->coherent_dma_mask;
-		if (dev->dma_mask)
-			dma_mask = *dev->dma_mask;
-	} else {
-		dma_mask = 0xfffffffful;
-	}
+	return r;
+}
 
-	/*
-	 * Platform devices, such as the internal USB, skip all
-	 * translation and use Octeon physical addresses directly.
-	 */
-	if (!dev || dev->bus == &platform_bus_type)
-		return physical;
+static void octeon_dma_sync_single_for_device(struct device *dev,
+	dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
+{
+	swiotlb_sync_single_for_device(dev, dma_handle, size, direction);
+	mb();
+}
 
-	switch (octeon_dma_bar_type) {
-	case OCTEON_DMA_BAR_TYPE_PCIE:
-		if (unlikely(physical < (16ul << 10)))
-			panic("dma_map_single: Not allowed to map first 16KB."
-			      " It interferes with BAR0 special area\n");
-		else if ((physical + size >= (256ul << 20)) &&
-			 (physical < (512ul << 20)))
-			panic("dma_map_single: Not allowed to map bootbus\n");
-		else if ((physical + size >= 0x400000000ull) &&
-			 physical < 0x410000000ull)
-			panic("dma_map_single: "
-			      "Attempt to map illegal memory address 0x%llx\n",
-			      physical);
-		else if (physical >= 0x420000000ull)
-			panic("dma_map_single: "
-			      "Attempt to map illegal memory address 0x%llx\n",
-			      physical);
-		else if (physical >= CVMX_PCIE_BAR1_PHYS_BASE &&
-			 physical + size < (CVMX_PCIE_BAR1_PHYS_BASE + CVMX_PCIE_BAR1_PHYS_SIZE)) {
-			result = physical - CVMX_PCIE_BAR1_PHYS_BASE + CVMX_PCIE_BAR1_RC_BASE;
-
-			if (((result+size-1) & dma_mask) != result+size-1)
-				panic("dma_map_single: Attempt to map address 0x%llx-0x%llx, which can't be accessed according to the dma mask 0x%llx\n",
-				      physical, physical+size-1, dma_mask);
-			goto done;
-		}
-
-		/* The 2nd 256MB is mapped at 256<<20 instead of 0x410000000 */
-		if ((physical >= 0x410000000ull) && physical < 0x420000000ull)
-			result = physical - 0x400000000ull;
-		else
-			result = physical;
-		if (((result+size-1) & dma_mask) != result+size-1)
-			panic("dma_map_single: Attempt to map address "
-			      "0x%llx-0x%llx, which can't be accessed "
-			      "according to the dma mask 0x%llx\n",
-			      physical, physical+size-1, dma_mask);
-		goto done;
+static void octeon_dma_sync_sg_for_device(struct device *dev,
+	struct scatterlist *sg, int nelems, enum dma_data_direction direction)
+{
+	swiotlb_sync_sg_for_device(dev, sg, nelems, direction);
+	mb();
+}
 
-	case OCTEON_DMA_BAR_TYPE_BIG:
-#ifdef CONFIG_64BIT
-		/* If the device supports 64bit addressing, then use BAR2 */
-		if (dma_mask > BAR2_PCI_ADDRESS) {
-			result = physical + BAR2_PCI_ADDRESS;
-			goto done;
-		}
-#endif
-		if (unlikely(physical < (4ul << 10))) {
-			panic("dma_map_single: Not allowed to map first 4KB. "
-			      "It interferes with BAR0 special area\n");
-		} else if (physical < (256ul << 20)) {
-			if (unlikely(physical + size > (256ul << 20)))
-				panic("dma_map_single: Requested memory spans "
-				      "Bar0 0:256MB and bootbus\n");
-			result = physical;
-			goto done;
-		} else if (unlikely(physical < (512ul << 20))) {
-			panic("dma_map_single: Not allowed to map bootbus\n");
-		} else if (physical < (2ul << 30)) {
-			if (unlikely(physical + size > (2ul << 30)))
-				panic("dma_map_single: Requested memory spans "
-				      "Bar0 512MB:2GB and BAR1\n");
-			result = physical;
-			goto done;
-		} else if (physical < (2ul << 30) + (128 << 20)) {
-			/* Fall through */
-		} else if (physical <
-			   (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20)) {
-			if (unlikely
-			    (physical + size >
-			     (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20)))
-				panic("dma_map_single: Requested memory "
-				      "extends past Bar1 (4GB-%luMB)\n",
-				      OCTEON_PCI_BAR1_HOLE_SIZE);
-			result = physical;
-			goto done;
-		} else if ((physical >= 0x410000000ull) &&
-			   (physical < 0x420000000ull)) {
-			if (unlikely(physical + size > 0x420000000ull))
-				panic("dma_map_single: Requested memory spans "
-				      "non existant memory\n");
-			/* BAR0 fixed mapping 256MB:512MB ->
-			 * 16GB+256MB:16GB+512MB */
-			result = physical - 0x400000000ull;
-			goto done;
-		} else {
-			/* Continued below switch statement */
-		}
-		break;
+static void *octeon_dma_alloc_coherent(struct device *dev, size_t size,
+	dma_addr_t *dma_handle, gfp_t gfp)
+{
+	void *ret;
 
-	case OCTEON_DMA_BAR_TYPE_SMALL:
-#ifdef CONFIG_64BIT
-		/* If the device supports 64bit addressing, then use BAR2 */
-		if (dma_mask > BAR2_PCI_ADDRESS) {
-			result = physical + BAR2_PCI_ADDRESS;
-			goto done;
-		}
+	if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
+		return ret;
+
+	/* ignore region specifiers */
+	gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
+
+#ifdef CONFIG_ZONE_DMA
+	if (dev == NULL)
+		gfp |= __GFP_DMA;
+	else if (dev->coherent_dma_mask <= DMA_BIT_MASK(24))
+		gfp |= __GFP_DMA;
+	else
 #endif
-		/* Continued below switch statement */
-		break;
+#ifdef CONFIG_ZONE_DMA32
+	     if (dev->coherent_dma_mask <= DMA_BIT_MASK(32))
+		gfp |= __GFP_DMA32;
+	else
+#endif
+		;
 
-	default:
-		panic("dma_map_single: Invalid octeon_dma_bar_type\n");
-	}
+	/* Don't invoke OOM killer */
+	gfp |= __GFP_NORETRY;
 
-	/* Don't allow mapping to span multiple Bar entries. The hardware guys
-	   won't guarantee that DMA across boards work */
-	if (unlikely((physical >> 22) != ((physical + size - 1) >> 22)))
-		panic("dma_map_single: "
-		      "Requested memory spans more than one Bar1 entry\n");
+	ret = swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
 
-	if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG)
-		start_index = 31;
-	else if (unlikely(dma_mask < (1ul << 27)))
-		start_index = (dma_mask >> 22);
-	else
-		start_index = 31;
-
-	/* Only one processor can access the Bar register at once */
-	raw_spin_lock_irqsave(&bar1_lock, flags);
-
-	/* Look through Bar1 for existing mapping that will work */
-	for (index = start_index; index >= 0; index--) {
-		if ((bar1_state[index].address_bits == physical >> 22) &&
-		    (bar1_state[index].ref_count)) {
-			/* An existing mapping will work, use it */
-			bar1_state[index].ref_count++;
-			if (unlikely(bar1_state[index].ref_count < 0))
-				panic("dma_map_single: "
-				      "Bar1[%d] reference count overflowed\n",
-				      (int) index);
-			result = (index << 22) | (physical & ((1 << 22) - 1));
-			/* Large BAR1 is offset at 2GB */
-			if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG)
-				result += 2ul << 30;
-			goto done_unlock;
-		}
-	}
+	mb();
 
-	/* No existing mappings, look for a free entry */
-	for (index = start_index; index >= 0; index--) {
-		if (unlikely(bar1_state[index].ref_count == 0)) {
-			union cvmx_pci_bar1_indexx bar1_index;
-			/* We have a free entry, use it */
-			bar1_state[index].ref_count = 1;
-			bar1_state[index].address_bits = physical >> 22;
-			bar1_index.u32 = 0;
-			/* Address bits[35:22] sent to L2C */
-			bar1_index.s.addr_idx = physical >> 22;
-			/* Don't put PCI accesses in L2. */
-			bar1_index.s.ca = 1;
-			/* Endian Swap Mode */
-			bar1_index.s.end_swp = 1;
-			/* Set '1' when the selected address range is valid. */
-			bar1_index.s.addr_v = 1;
-			octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index),
-					   bar1_index.u32);
-			/* An existing mapping will work, use it */
-			result = (index << 22) | (physical & ((1 << 22) - 1));
-			/* Large BAR1 is offset at 2GB */
-			if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG)
-				result += 2ul << 30;
-			goto done_unlock;
-		}
-	}
+	return ret;
+}
+
+static void octeon_dma_free_coherent(struct device *dev, size_t size,
+	void *vaddr, dma_addr_t dma_handle)
+{
+	int order = get_order(size);
 
-	pr_err("dma_map_single: "
-	       "Can't find empty BAR1 index for physical mapping 0x%llx\n",
-	       (unsigned long long) physical);
+	if (dma_release_from_coherent(dev, order, vaddr))
+		return;
 
-done_unlock:
-	raw_spin_unlock_irqrestore(&bar1_lock, flags);
-done:
-	pr_debug("dma_map_single 0x%llx->0x%llx\n", physical, result);
-	return result;
-#endif
+	swiotlb_free_coherent(dev, size, vaddr, dma_handle);
 }
 
-void octeon_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
+static struct mips_dma_map_ops octeon_linear_dma_map_ops = {
+	.dma_map_ops = {
+		.alloc_coherent = octeon_dma_alloc_coherent,
+		.free_coherent = octeon_dma_free_coherent,
+		.map_page = octeon_dma_map_page,
+		.unmap_page = swiotlb_unmap_page,
+		.map_sg = octeon_dma_map_sg,
+		.unmap_sg = swiotlb_unmap_sg_attrs,
+		.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
+		.sync_single_for_device = octeon_dma_sync_single_for_device,
+		.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
+		.sync_sg_for_device = octeon_dma_sync_sg_for_device,
+		.mapping_error = swiotlb_dma_mapping_error,
+		.dma_supported = swiotlb_dma_supported
+	},
+	.phys_to_dma = mips_unity_phys_to_dma,
+	.dma_to_phys = mips_unity_dma_to_phys
+};
+
+void __init plat_swiotlb_setup(void)
 {
-#ifndef CONFIG_PCI
-	/*
-	 * Without PCI/PCIe this function can be called for Octeon internal
-	 * devices such as USB. These devices all support 64bit addressing.
-	 */
-	return;
-#else
-	unsigned long flags;
-	uint64_t index;
+	int i;
+	phys_t max_addr;
+	phys_t addr_size;
+	size_t swiotlbsize;
 
+	max_addr = 0;
+	addr_size = 0;
+
+	for (i = 0 ; i < boot_mem_map.nr_map; i++) {
+		struct boot_mem_map_entry *e = &boot_mem_map.map[i];
+		if (e->type != BOOT_MEM_RAM)
+			continue;
+
+		/* These addresses map low for PCI. */
+		if (e->addr > 0x410000000ull)
+			continue;
+
+		addr_size += e->size;
+
+		if (max_addr < e->addr + e->size)
+			max_addr = e->addr + e->size;
+
+	}
+
+	swiotlbsize = PAGE_SIZE;
+
+#ifdef CONFIG_PCI
 	/*
-	 * Platform devices, such as the internal USB, skip all
-	 * translation and use Octeon physical addresses directly.
+	 * For OCTEON_DMA_BAR_TYPE_SMALL, size the iotlb at 1/4 memory
+	 * size to a maximum of 64MB
 	 */
-	if (dev->bus == &platform_bus_type)
-		return;
+	if (OCTEON_IS_MODEL(OCTEON_CN31XX)
+	    || OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2)) {
+		swiotlbsize = addr_size / 4;
+		if (swiotlbsize > 64 * (1<<20))
+			swiotlbsize = 64 * (1<<20);
+	} else if (max_addr > 0xf0000000ul) {
+		/*
+		 * Otherwise only allocate a big iotlb if there is
+		 * memory past the BAR1 hole.
+		 */
+		swiotlbsize = 64 * (1<<20);
+	}
+#endif
+
+	swiotlb_init_with_default_size(swiotlbsize, 1);
+
+	mips_dma_map_ops = &octeon_linear_dma_map_ops;
+}
+
+#ifdef CONFIG_PCI
+struct mips_dma_map_ops octeon_pci_dma_map_ops = {
+	.dma_map_ops = {
+		.alloc_coherent = octeon_dma_alloc_coherent,
+		.free_coherent = octeon_dma_free_coherent,
+		.map_page = octeon_dma_map_page,
+		.unmap_page = swiotlb_unmap_page,
+		.map_sg = octeon_dma_map_sg,
+		.unmap_sg = swiotlb_unmap_sg_attrs,
+		.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
+		.sync_single_for_device = octeon_dma_sync_single_for_device,
+		.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
+		.sync_sg_for_device = octeon_dma_sync_sg_for_device,
+		.mapping_error = swiotlb_dma_mapping_error,
+		.dma_supported = swiotlb_dma_supported
+	},
+};
 
+void __init octeon_pci_dma_init(void)
+{
 	switch (octeon_dma_bar_type) {
 	case OCTEON_DMA_BAR_TYPE_PCIE:
-		/* Nothing to do, all mappings are static */
-		goto done;
-
+		octeon_pci_dma_map_ops.phys_to_dma = octeon_gen1_phys_to_dma;
+		octeon_pci_dma_map_ops.dma_to_phys = octeon_gen1_dma_to_phys;
+		break;
 	case OCTEON_DMA_BAR_TYPE_BIG:
-#ifdef CONFIG_64BIT
-		/* Nothing to do for addresses using BAR2 */
-		if (dma_addr >= BAR2_PCI_ADDRESS)
-			goto done;
-#endif
-		if (unlikely(dma_addr < (4ul << 10)))
-			panic("dma_unmap_single: Unexpect DMA address 0x%llx\n",
-			      dma_addr);
-		else if (dma_addr < (2ul << 30))
-			/* Nothing to do for addresses using BAR0 */
-			goto done;
-		else if (dma_addr < (2ul << 30) + (128ul << 20))
-			/* Need to unmap, fall through */
-			index = (dma_addr - (2ul << 30)) >> 22;
-		else if (dma_addr <
-			 (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20))
-			goto done;	/* Nothing to do for the rest of BAR1 */
-		else
-			panic("dma_unmap_single: Unexpect DMA address 0x%llx\n",
-			      dma_addr);
-		/* Continued below switch statement */
+		octeon_pci_dma_map_ops.phys_to_dma = octeon_big_phys_to_dma;
+		octeon_pci_dma_map_ops.dma_to_phys = octeon_big_dma_to_phys;
 		break;
-
 	case OCTEON_DMA_BAR_TYPE_SMALL:
-#ifdef CONFIG_64BIT
-		/* Nothing to do for addresses using BAR2 */
-		if (dma_addr >= BAR2_PCI_ADDRESS)
-			goto done;
-#endif
-		index = dma_addr >> 22;
-		/* Continued below switch statement */
+		octeon_pci_dma_map_ops.phys_to_dma = octeon_small_phys_to_dma;
+		octeon_pci_dma_map_ops.dma_to_phys = octeon_small_dma_to_phys;
 		break;
-
 	default:
-		panic("dma_unmap_single: Invalid octeon_dma_bar_type\n");
+		break;
 	}
-
-	if (unlikely(index > 31))
-		panic("dma_unmap_single: "
-		      "Attempt to unmap an invalid address (0x%llx)\n",
-		      dma_addr);
-
-	raw_spin_lock_irqsave(&bar1_lock, flags);
-	bar1_state[index].ref_count--;
-	if (bar1_state[index].ref_count == 0)
-		octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index), 0);
-	else if (unlikely(bar1_state[index].ref_count < 0))
-		panic("dma_unmap_single: Bar1[%u] reference count < 0\n",
-		      (int) index);
-	raw_spin_unlock_irqrestore(&bar1_lock, flags);
-done:
-	pr_debug("dma_unmap_single 0x%llx\n", dma_addr);
-	return;
-#endif
 }
+#endif /* CONFIG_PCI */
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 17d5794..a0058fb 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
@@ -15,41 +15,40 @@
 
 struct device;
 
-dma_addr_t octeon_map_dma_mem(struct device *, void *, size_t);
-void octeon_unmap_dma_mem(struct device *, dma_addr_t);
+void octeon_pci_dma_init(void);
 
 static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
 	size_t size)
 {
-	return octeon_map_dma_mem(dev, addr, size);
+	BUG();
 }
 
 static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
 	struct page *page)
 {
-	return octeon_map_dma_mem(dev, page_address(page), PAGE_SIZE);
+	BUG();
 }
 
 static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
 	dma_addr_t dma_addr)
 {
-	return dma_addr;
+	BUG();
 }
 
 static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
 	size_t size, enum dma_data_direction direction)
 {
-	octeon_unmap_dma_mem(dev, dma_addr);
+	BUG();
 }
 
 static inline int plat_dma_supported(struct device *dev, u64 mask)
 {
-	return 1;
+	BUG();
 }
 
 static inline void plat_extra_sync_for_device(struct device *dev)
 {
-	mb();
+	BUG();
 }
 
 static inline int plat_device_is_coherent(struct device *dev)
@@ -60,7 +59,9 @@ static inline int plat_device_is_coherent(struct device *dev)
 static inline int plat_dma_mapping_error(struct device *dev,
 					 dma_addr_t dma_addr)
 {
-	return dma_addr == -1;
+	BUG();
 }
 
+extern struct mips_dma_map_ops octeon_pci_dma_map_ops;
+
 #endif /* __ASM_MACH_CAVIUM_OCTEON_DMA_COHERENCE_H */
diff --git a/arch/mips/include/asm/octeon/pci-octeon.h b/arch/mips/include/asm/octeon/pci-octeon.h
index ece7804..fba2ba2 100644
--- a/arch/mips/include/asm/octeon/pci-octeon.h
+++ b/arch/mips/include/asm/octeon/pci-octeon.h
@@ -36,6 +36,16 @@ extern int (*octeon_pcibios_map_irq)(const struct pci_dev *dev,
 				     u8 slot, u8 pin);
 
 /*
+ * For PCI (not PCIe) the BAR2 base address.
+ */
+#define OCTEON_BAR2_PCI_ADDRESS 0x8000000000ull
+
+/*
+ * For PCI (not PCIe) the base of the memory mapped by BAR1
+ */
+extern u64 octeon_bar1_pci_phys;
+
+/*
  * The following defines are used when octeon_dma_bar_type =
  * OCTEON_DMA_BAR_TYPE_BIG
  */
diff --git a/arch/mips/pci/pci-octeon.c b/arch/mips/pci/pci-octeon.c
index d248b70..311d808 100644
--- a/arch/mips/pci/pci-octeon.c
+++ b/arch/mips/pci/pci-octeon.c
@@ -11,6 +11,7 @@
 #include <linux/interrupt.h>
 #include <linux/time.h>
 #include <linux/delay.h>
+#include <linux/swiotlb.h>
 
 #include <asm/time.h>
 
@@ -19,6 +20,8 @@
 #include <asm/octeon/cvmx-pci-defs.h>
 #include <asm/octeon/pci-octeon.h>
 
+#include <dma-coherence.h>
+
 #define USE_OCTEON_INTERNAL_ARBITER
 
 /*
@@ -32,6 +35,8 @@
 /* Octeon't PCI controller uses did=3, subdid=3 for PCI memory. */
 #define OCTEON_PCI_MEMSPACE_OFFSET  (0x00011b0000000000ull)
 
+u64 octeon_bar1_pci_phys;
+
 /**
  * This is the bit decoding used for the Octeon PCI controller addresses
  */
@@ -170,6 +175,8 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
 		pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, dconfig);
 	}
 
+	dev->dev.archdata.dma_ops = &octeon_pci_dma_map_ops;
+
 	return 0;
 }
 
@@ -618,12 +625,10 @@ static int __init octeon_pci_setup(void)
 	 * before the readl()'s below. We don't want BAR2 overlapping
 	 * with BAR0/BAR1 during these reads.
 	 */
-	octeon_npi_write32(CVMX_NPI_PCI_CFG08, 0);
-	octeon_npi_write32(CVMX_NPI_PCI_CFG09, 0x80);
-
-	/* Disable the BAR1 movable mappings */
-	for (index = 0; index < 32; index++)
-		octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index), 0);
+	octeon_npi_write32(CVMX_NPI_PCI_CFG08,
+			   (u32)(OCTEON_BAR2_PCI_ADDRESS & 0xffffffffull));
+	octeon_npi_write32(CVMX_NPI_PCI_CFG09,
+			   (u32)(OCTEON_BAR2_PCI_ADDRESS >> 32));
 
 	if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) {
 		/* Remap the Octeon BAR 0 to 0-2GB */
@@ -637,6 +642,25 @@ static int __init octeon_pci_setup(void)
 		octeon_npi_write32(CVMX_NPI_PCI_CFG06, 2ul << 30);
 		octeon_npi_write32(CVMX_NPI_PCI_CFG07, 0);
 
+		/* BAR1 movable mappings set for identity mapping */
+		octeon_bar1_pci_phys = 0x80000000ull;
+		for (index = 0; index < 32; index++) {
+			union cvmx_pci_bar1_indexx bar1_index;
+
+			bar1_index.u32 = 0;
+			/* Address bits[35:22] sent to L2C */
+			bar1_index.s.addr_idx =
+				(octeon_bar1_pci_phys >> 22) + index;
+			/* Don't put PCI accesses in L2. */
+			bar1_index.s.ca = 1;
+			/* Endian Swap Mode */
+			bar1_index.s.end_swp = 1;
+			/* Set '1' when the selected address range is valid. */
+			bar1_index.s.addr_v = 1;
+			octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index),
+					   bar1_index.u32);
+		}
+
 		/* Devices go after BAR1 */
 		octeon_pci_mem_resource.start =
 			OCTEON_PCI_MEMSPACE_OFFSET + (4ul << 30) -
@@ -652,6 +676,27 @@ static int __init octeon_pci_setup(void)
 		octeon_npi_write32(CVMX_NPI_PCI_CFG06, 0);
 		octeon_npi_write32(CVMX_NPI_PCI_CFG07, 0);
 
+		/* BAR1 movable regions contiguous to cover the swiotlb */
+		octeon_bar1_pci_phys =
+			virt_to_phys(swiotlb_start) & ~((1ull << 22) - 1);
+
+		for (index = 0; index < 32; index++) {
+			union cvmx_pci_bar1_indexx bar1_index;
+
+			bar1_index.u32 = 0;
+			/* Address bits[35:22] sent to L2C */
+			bar1_index.s.addr_idx =
+				(octeon_bar1_pci_phys >> 22) + index;
+			/* Don't put PCI accesses in L2. */
+			bar1_index.s.ca = 1;
+			/* Endian Swap Mode */
+			bar1_index.s.end_swp = 1;
+			/* Set '1' when the selected address range is valid. */
+			bar1_index.s.addr_v = 1;
+			octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index),
+					   bar1_index.u32);
+		}
+
 		/* Devices go after BAR0 */
 		octeon_pci_mem_resource.start =
 			OCTEON_PCI_MEMSPACE_OFFSET + (128ul << 20) +
@@ -667,6 +712,9 @@ static int __init octeon_pci_setup(void)
 	 * was setup properly.
 	 */
 	cvmx_write_csr(CVMX_NPI_PCI_INT_SUM2, -1);
+
+	octeon_pci_dma_init();
+
 	return 0;
 }
 
diff --git a/arch/mips/pci/pcie-octeon.c b/arch/mips/pci/pcie-octeon.c
index 861361e..385f035 100644
--- a/arch/mips/pci/pcie-octeon.c
+++ b/arch/mips/pci/pcie-octeon.c
@@ -75,6 +75,8 @@ union cvmx_pcie_address {
 	} mem;
 };
 
+#include <dma-coherence.h>
+
 /**
  * Return the Core virtual base address for PCIe IO access. IOs are
  * read/written as an offset from this address.
@@ -1391,6 +1393,9 @@ static int __init octeon_pcie_setup(void)
 			cvmx_pcie_get_io_size(1) - 1;
 		register_pci_controller(&octeon_pcie1_controller);
 	}
+
+	octeon_pci_dma_init();
+
 	return 0;
 }
 
-- 
1.7.2.2


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

* [PATCH 6/9] swiotlb: Declare swiotlb_init_with_default_size()
  2010-09-23 22:38 [PATCH 0/9] MIPS: Use dma-mapping-common.h and use swiotlb for Octeon David Daney
                   ` (6 preceding siblings ...)
  2010-09-23 22:38 ` [PATCH 9/9] MIPS: Octeon: Rewrite DMA mapping functions David Daney
@ 2010-09-23 22:47 ` David Daney
  2010-09-27 16:53   ` Konrad Rzeszutek Wilk
  2010-09-23 22:47 ` [PATCH 7/9] swiotlb: Make bounce buffer bounds non-static David Daney
  8 siblings, 1 reply; 21+ messages in thread
From: David Daney @ 2010-09-23 22:47 UTC (permalink / raw)
  To: linux-mips, ralf, linux-kernel
  Cc: David Daney, Andrew Morton, FUJITA Tomonori,
	Konrad Rzeszutek Wilk, Ingo Molnar, Andre Goddard Rosa

It comes from swiotlb.c and must be called by external code, so declare it.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Andre Goddard Rosa <andre.goddard@gmail.com>
---
 include/linux/swiotlb.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 8c0e349..dba51fe 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -23,6 +23,7 @@ extern int swiotlb_force;
 #define IO_TLB_SHIFT 11
 
 extern void swiotlb_init(int verbose);
+extern void swiotlb_init_with_default_size(size_t, int);
 extern void swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
 
 /*
-- 
1.7.2.2


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

* [PATCH 7/9] swiotlb: Make bounce buffer bounds non-static.
  2010-09-23 22:38 [PATCH 0/9] MIPS: Use dma-mapping-common.h and use swiotlb for Octeon David Daney
                   ` (7 preceding siblings ...)
  2010-09-23 22:47 ` [PATCH 6/9] swiotlb: Declare swiotlb_init_with_default_size() David Daney
@ 2010-09-23 22:47 ` David Daney
  2010-09-27  5:20   ` FUJITA Tomonori
  8 siblings, 1 reply; 21+ messages in thread
From: David Daney @ 2010-09-23 22:47 UTC (permalink / raw)
  To: linux-mips, ralf, linux-kernel
  Cc: David Daney, Andrew Morton, FUJITA Tomonori,
	Konrad Rzeszutek Wilk, Ingo Molnar, Andre Goddard Rosa

Octeon PCI mapping has to be established to cover the bounce buffers,
so it has to have access to the bounds.

Rename the bounds variables to match the names of other parts of swiotlb.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Andre Goddard Rosa <andre.goddard@gmail.com>
---
 include/linux/swiotlb.h |    6 ++++
 lib/swiotlb.c           |   62 +++++++++++++++++++++++-----------------------
 2 files changed, 37 insertions(+), 31 deletions(-)

diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index dba51fe..0b8fbe9 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -22,6 +22,12 @@ extern int swiotlb_force;
  */
 #define IO_TLB_SHIFT 11
 
+/*
+ * The memory range used by the swiotlb
+ */
+extern char *swiotlb_start;
+extern char *swiotlb_end;
+
 extern void swiotlb_init(int verbose);
 extern void swiotlb_init_with_default_size(size_t, int);
 extern void swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 34e3082..4cb4ad7 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -57,11 +57,11 @@ int swiotlb_force;
  * swiotlb_tbl_sync_single_*, to see if the memory was in fact allocated by this
  * API.
  */
-static char *io_tlb_start, *io_tlb_end;
+char *swiotlb_start, *swiotlb_end;
 
 /*
- * The number of IO TLB blocks (in groups of 64) betweeen io_tlb_start and
- * io_tlb_end.  This is command line adjustable via setup_io_tlb_npages.
+ * The number of IO TLB blocks (in groups of 64) betweeen swiotlb_start and
+ * swiotlb_end.  This is command line adjustable via setup_io_tlb_npages.
  */
 static unsigned long io_tlb_nslabs;
 
@@ -122,11 +122,11 @@ void swiotlb_print_info(void)
 	unsigned long bytes = io_tlb_nslabs << IO_TLB_SHIFT;
 	phys_addr_t pstart, pend;
 
-	pstart = virt_to_phys(io_tlb_start);
-	pend = virt_to_phys(io_tlb_end);
+	pstart = virt_to_phys(swiotlb_start);
+	pend = virt_to_phys(swiotlb_end);
 
 	printk(KERN_INFO "Placing %luMB software IO TLB between %p - %p\n",
-	       bytes >> 20, io_tlb_start, io_tlb_end);
+	       bytes >> 20, swiotlb_start, swiotlb_end);
 	printk(KERN_INFO "software IO TLB at phys %#llx - %#llx\n",
 	       (unsigned long long)pstart,
 	       (unsigned long long)pend);
@@ -139,13 +139,13 @@ void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
 	bytes = nslabs << IO_TLB_SHIFT;
 
 	io_tlb_nslabs = nslabs;
-	io_tlb_start = tlb;
-	io_tlb_end = io_tlb_start + bytes;
+	swiotlb_start = tlb;
+	swiotlb_end = swiotlb_start + bytes;
 
 	/*
 	 * Allocate and initialize the free list array.  This array is used
 	 * to find contiguous free memory regions of size up to IO_TLB_SEGSIZE
-	 * between io_tlb_start and io_tlb_end.
+	 * between swiotlb_start and swiotlb_end.
 	 */
 	io_tlb_list = alloc_bootmem(io_tlb_nslabs * sizeof(int));
 	for (i = 0; i < io_tlb_nslabs; i++)
@@ -182,11 +182,11 @@ swiotlb_init_with_default_size(size_t default_size, int verbose)
 	/*
 	 * Get IO TLB memory from the low pages
 	 */
-	io_tlb_start = alloc_bootmem_low_pages(bytes);
-	if (!io_tlb_start)
+	swiotlb_start = alloc_bootmem_low_pages(bytes);
+	if (!swiotlb_start)
 		panic("Cannot allocate SWIOTLB buffer");
 
-	swiotlb_init_with_tbl(io_tlb_start, io_tlb_nslabs, verbose);
+	swiotlb_init_with_tbl(swiotlb_start, io_tlb_nslabs, verbose);
 }
 
 void __init
@@ -219,14 +219,14 @@ swiotlb_late_init_with_default_size(size_t default_size)
 	bytes = io_tlb_nslabs << IO_TLB_SHIFT;
 
 	while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) {
-		io_tlb_start = (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN,
-							order);
-		if (io_tlb_start)
+		swiotlb_start =
+			(void *)__get_free_pages(GFP_DMA | __GFP_NOWARN, order);
+		if (swiotlb_start)
 			break;
 		order--;
 	}
 
-	if (!io_tlb_start)
+	if (!swiotlb_start)
 		goto cleanup1;
 
 	if (order != get_order(bytes)) {
@@ -235,13 +235,13 @@ swiotlb_late_init_with_default_size(size_t default_size)
 		io_tlb_nslabs = SLABS_PER_PAGE << order;
 		bytes = io_tlb_nslabs << IO_TLB_SHIFT;
 	}
-	io_tlb_end = io_tlb_start + bytes;
-	memset(io_tlb_start, 0, bytes);
+	swiotlb_end = swiotlb_start + bytes;
+	memset(swiotlb_start, 0, bytes);
 
 	/*
 	 * Allocate and initialize the free list array.  This array is used
 	 * to find contiguous free memory regions of size up to IO_TLB_SEGSIZE
-	 * between io_tlb_start and io_tlb_end.
+	 * between swiotlb_start and swiotlb_end.
 	 */
 	io_tlb_list = (unsigned int *)__get_free_pages(GFP_KERNEL,
 	                              get_order(io_tlb_nslabs * sizeof(int)));
@@ -284,9 +284,9 @@ cleanup3:
 	                                                 sizeof(int)));
 	io_tlb_list = NULL;
 cleanup2:
-	io_tlb_end = NULL;
-	free_pages((unsigned long)io_tlb_start, order);
-	io_tlb_start = NULL;
+	swiotlb_end = NULL;
+	free_pages((unsigned long)swiotlb_start, order);
+	swiotlb_start = NULL;
 cleanup1:
 	io_tlb_nslabs = req_nslabs;
 	return -ENOMEM;
@@ -304,7 +304,7 @@ void __init swiotlb_free(void)
 			   get_order(io_tlb_nslabs * sizeof(phys_addr_t)));
 		free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs *
 								 sizeof(int)));
-		free_pages((unsigned long)io_tlb_start,
+		free_pages((unsigned long)swiotlb_start,
 			   get_order(io_tlb_nslabs << IO_TLB_SHIFT));
 	} else {
 		free_bootmem_late(__pa(io_tlb_overflow_buffer),
@@ -313,15 +313,15 @@ void __init swiotlb_free(void)
 				  io_tlb_nslabs * sizeof(phys_addr_t));
 		free_bootmem_late(__pa(io_tlb_list),
 				  io_tlb_nslabs * sizeof(int));
-		free_bootmem_late(__pa(io_tlb_start),
+		free_bootmem_late(__pa(swiotlb_start),
 				  io_tlb_nslabs << IO_TLB_SHIFT);
 	}
 }
 
 static int is_swiotlb_buffer(phys_addr_t paddr)
 {
-	return paddr >= virt_to_phys(io_tlb_start) &&
-		paddr < virt_to_phys(io_tlb_end);
+	return paddr >= virt_to_phys(swiotlb_start) &&
+		paddr < virt_to_phys(swiotlb_end);
 }
 
 /*
@@ -435,7 +435,7 @@ void *swiotlb_tbl_map_single(struct device *hwdev, dma_addr_t tbl_dma_addr,
 				io_tlb_list[i] = 0;
 			for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE - 1) && io_tlb_list[i]; i--)
 				io_tlb_list[i] = ++count;
-			dma_addr = io_tlb_start + (index << IO_TLB_SHIFT);
+			dma_addr = swiotlb_start + (index << IO_TLB_SHIFT);
 
 			/*
 			 * Update the indices to avoid searching in the next
@@ -479,7 +479,7 @@ static void *
 map_single(struct device *hwdev, phys_addr_t phys, size_t size,
 	   enum dma_data_direction dir)
 {
-	dma_addr_t start_dma_addr = swiotlb_virt_to_bus(hwdev, io_tlb_start);
+	dma_addr_t start_dma_addr = swiotlb_virt_to_bus(hwdev, swiotlb_start);
 
 	return swiotlb_tbl_map_single(hwdev, start_dma_addr, phys, size, dir);
 }
@@ -493,7 +493,7 @@ swiotlb_tbl_unmap_single(struct device *hwdev, char *dma_addr, size_t size,
 {
 	unsigned long flags;
 	int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
-	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
+	int index = (dma_addr - swiotlb_start) >> IO_TLB_SHIFT;
 	phys_addr_t phys = io_tlb_orig_addr[index];
 
 	/*
@@ -534,7 +534,7 @@ swiotlb_tbl_sync_single(struct device *hwdev, char *dma_addr, size_t size,
 			enum dma_data_direction dir,
 			enum dma_sync_target target)
 {
-	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
+	int index = (dma_addr - swiotlb_start) >> IO_TLB_SHIFT;
 	phys_addr_t phys = io_tlb_orig_addr[index];
 
 	phys += ((unsigned long)dma_addr & ((1 << IO_TLB_SHIFT) - 1));
@@ -918,6 +918,6 @@ EXPORT_SYMBOL(swiotlb_dma_mapping_error);
 int
 swiotlb_dma_supported(struct device *hwdev, u64 mask)
 {
-	return swiotlb_virt_to_bus(hwdev, io_tlb_end - 1) <= mask;
+	return swiotlb_virt_to_bus(hwdev, swiotlb_end - 1) <= mask;
 }
 EXPORT_SYMBOL(swiotlb_dma_supported);
-- 
1.7.2.2


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

* [PATCH] MIPS: Remove plat_map_dma_mem_page().
  2010-09-23 22:38 ` [PATCH 5/9] MIPS: Convert DMA to use dma-mapping-common.h David Daney
@ 2010-09-24  1:03   ` David Daney
  2010-09-27  5:30   ` [PATCH 5/9] MIPS: Convert DMA to use dma-mapping-common.h FUJITA Tomonori
  1 sibling, 0 replies; 21+ messages in thread
From: David Daney @ 2010-09-24  1:03 UTC (permalink / raw)
  To: linux-mips, ralf, linux-kernel; +Cc: David Daney, Wu Zhangjin, David VomLehn

It is now unused.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Cc: Wu Zhangjin <wuzhangjin@gmail.com>
Cc: David VomLehn <dvomlehn@cisco.com>
---

This is a small addition to the rest of the patch set.  It could be
rolled into [PATCH 5/9] MIPS: Convert DMA to use dma-mapping-common.h

 arch/mips/include/asm/mach-generic/dma-coherence.h |    6 ------
 arch/mips/include/asm/mach-ip27/dma-coherence.h    |    7 -------
 arch/mips/include/asm/mach-ip32/dma-coherence.h    |   12 ------------
 arch/mips/include/asm/mach-jazz/dma-coherence.h    |    5 -----
 .../mips/include/asm/mach-loongson/dma-coherence.h |    6 ------
 arch/mips/include/asm/mach-powertv/dma-coherence.h |    6 ------
 6 files changed, 0 insertions(+), 42 deletions(-)

diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h
index 8da9807..8259966 100644
--- a/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ b/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -17,12 +17,6 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
 	return virt_to_phys(addr);
 }
 
-static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
-	struct page *page)
-{
-	return page_to_phys(page);
-}
-
 static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
 	dma_addr_t dma_addr)
 {
diff --git a/arch/mips/include/asm/mach-ip27/dma-coherence.h b/arch/mips/include/asm/mach-ip27/dma-coherence.h
index d3d0401..e35bfbc 100644
--- a/arch/mips/include/asm/mach-ip27/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip27/dma-coherence.h
@@ -26,13 +26,6 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
 	return pa;
 }
 
-static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page)
-{
-	dma_addr_t pa = dev_to_baddr(dev, page_to_phys(page));
-
-	return pa;
-}
-
 static unsigned long plat_dma_addr_to_phys(struct device *dev,
 	dma_addr_t dma_addr)
 {
diff --git a/arch/mips/include/asm/mach-ip32/dma-coherence.h b/arch/mips/include/asm/mach-ip32/dma-coherence.h
index 3785595..7dd1907 100644
--- a/arch/mips/include/asm/mach-ip32/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip32/dma-coherence.h
@@ -37,18 +37,6 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
 	return pa;
 }
 
-static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page)
-{
-	dma_addr_t pa;
-
-	pa = page_to_phys(page) & RAM_OFFSET_MASK;
-
-	if (dev == NULL)
-		pa += CRIME_HI_MEM_BASE;
-
-	return pa;
-}
-
 /* This is almost certainly wrong but it's what dma-ip32.c used to use  */
 static unsigned long plat_dma_addr_to_phys(struct device *dev,
 	dma_addr_t dma_addr)
diff --git a/arch/mips/include/asm/mach-jazz/dma-coherence.h b/arch/mips/include/asm/mach-jazz/dma-coherence.h
index f93aee5..e0d340b 100644
--- a/arch/mips/include/asm/mach-jazz/dma-coherence.h
+++ b/arch/mips/include/asm/mach-jazz/dma-coherence.h
@@ -17,11 +17,6 @@ static dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size)
 	return vdma_alloc(virt_to_phys(addr), size);
 }
 
-static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page)
-{
-	return vdma_alloc(page_to_phys(page), PAGE_SIZE);
-}
-
 static unsigned long plat_dma_addr_to_phys(struct device *dev,
 	dma_addr_t dma_addr)
 {
diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h
index 981c75f..8daeaee 100644
--- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
+++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
@@ -19,12 +19,6 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
 	return virt_to_phys(addr) | 0x80000000;
 }
 
-static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
-					       struct page *page)
-{
-	return page_to_phys(page) | 0x80000000;
-}
-
 static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
 	dma_addr_t dma_addr)
 {
diff --git a/arch/mips/include/asm/mach-powertv/dma-coherence.h b/arch/mips/include/asm/mach-powertv/dma-coherence.h
index f76029c..647de8c 100644
--- a/arch/mips/include/asm/mach-powertv/dma-coherence.h
+++ b/arch/mips/include/asm/mach-powertv/dma-coherence.h
@@ -70,12 +70,6 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
 		return phys_to_dma(virt_to_phys(addr));
 }
 
-static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
-	struct page *page)
-{
-	return phys_to_dma(page_to_phys(page));
-}
-
 static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
 	dma_addr_t dma_addr)
 {
-- 
1.7.2.2


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

* [PATCH] MIPS: Octeon: Remove plat_map_dma_mem_page().
  2010-09-23 22:38 ` [PATCH 9/9] MIPS: Octeon: Rewrite DMA mapping functions David Daney
@ 2010-09-24  1:06   ` David Daney
  0 siblings, 0 replies; 21+ messages in thread
From: David Daney @ 2010-09-24  1:06 UTC (permalink / raw)
  To: linux-mips, ralf, linux-kernel; +Cc: David Daney

It is now unused.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---

This is a small addition to the rest of the patch set.  It could be
rolled into [PATCH 9/9] MIPS: Octeon: Rewrite DMA mapping functions.

 .../include/asm/mach-cavium-octeon/dma-coherence.h |    6 ------
 1 files changed, 0 insertions(+), 6 deletions(-)

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 a0058fb..cedf254 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
@@ -23,12 +23,6 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
 	BUG();
 }
 
-static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
-	struct page *page)
-{
-	BUG();
-}
-
 static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
 	dma_addr_t dma_addr)
 {
-- 
1.7.2.2


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

* Re: [PATCH 8/9] MIPS: Add a platform hook for swiotlb setup.
  2010-09-23 22:38 ` [PATCH 8/9] MIPS: Add a platform hook for swiotlb setup David Daney
@ 2010-09-24 16:08   ` Sergei Shtylyov
  2010-09-24 16:13     ` David Daney
  0 siblings, 1 reply; 21+ messages in thread
From: Sergei Shtylyov @ 2010-09-24 16:08 UTC (permalink / raw)
  To: David Daney; +Cc: linux-mips, ralf, linux-kernel

Hello.

David Daney wrote:

> This allows platforms that are using the swiotlb to initialize it.

> Signed-off-by: David Daney <ddaney@caviumnetworks.com>
> ---
>  arch/mips/include/asm/bootinfo.h |    5 +++++
>  arch/mips/kernel/setup.c         |    5 +++++
>  2 files changed, 10 insertions(+), 0 deletions(-)

> diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
> index 15a8ef0..b3cf989 100644
> --- a/arch/mips/include/asm/bootinfo.h
> +++ b/arch/mips/include/asm/bootinfo.h
> @@ -125,4 +125,9 @@ extern unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3;
>   */
>  extern void plat_mem_setup(void);
>  
> +/*
> + * Optional platform hook to call swiotlb_setup().
> + */
> +extern void plat_swiotlb_setup(void);
> +
>  #endif /* _ASM_BOOTINFO_H */
> diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
> index 85aef3f..8b650da 100644
> --- a/arch/mips/kernel/setup.c
> +++ b/arch/mips/kernel/setup.c
> @@ -488,6 +488,11 @@ static void __init arch_mem_init(char **cmdline_p)
>  
>  	bootmem_init();
>  	sparse_init();
> +
> +#ifdef CONFIG_SWIOTLB
> +	plat_swiotlb_setup();
> +#endif

    We should avoid #ifdef's in function bodies. Why not defile an empty 
'inline' in the header above if CONFIG_SWIOTLB is not defined?

WBR, Sergei


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

* Re: [PATCH 8/9] MIPS: Add a platform hook for swiotlb setup.
  2010-09-24 16:08   ` Sergei Shtylyov
@ 2010-09-24 16:13     ` David Daney
  2010-09-24 16:32       ` Ralf Baechle
  0 siblings, 1 reply; 21+ messages in thread
From: David Daney @ 2010-09-24 16:13 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: linux-mips, ralf, linux-kernel

On 09/24/2010 09:08 AM, Sergei Shtylyov wrote:
> Hello.
>
> David Daney wrote:
>
>> This allows platforms that are using the swiotlb to initialize it.
>
>> Signed-off-by: David Daney <ddaney@caviumnetworks.com>
>> ---
>> arch/mips/include/asm/bootinfo.h | 5 +++++
>> arch/mips/kernel/setup.c | 5 +++++
>> 2 files changed, 10 insertions(+), 0 deletions(-)
>
>> diff --git a/arch/mips/include/asm/bootinfo.h
>> b/arch/mips/include/asm/bootinfo.h
>> index 15a8ef0..b3cf989 100644
>> --- a/arch/mips/include/asm/bootinfo.h
>> +++ b/arch/mips/include/asm/bootinfo.h
>> @@ -125,4 +125,9 @@ extern unsigned long fw_arg0, fw_arg1, fw_arg2,
>> fw_arg3;
>> */
>> extern void plat_mem_setup(void);
>>
>> +/*
>> + * Optional platform hook to call swiotlb_setup().
>> + */
>> +extern void plat_swiotlb_setup(void);
>> +
>> #endif /* _ASM_BOOTINFO_H */
>> diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
>> index 85aef3f..8b650da 100644
>> --- a/arch/mips/kernel/setup.c
>> +++ b/arch/mips/kernel/setup.c
>> @@ -488,6 +488,11 @@ static void __init arch_mem_init(char **cmdline_p)
>>
>> bootmem_init();
>> sparse_init();
>> +
>> +#ifdef CONFIG_SWIOTLB
>> + plat_swiotlb_setup();
>> +#endif
>
> We should avoid #ifdef's in function bodies. Why not defile an empty
> 'inline' in the header above if CONFIG_SWIOTLB is not defined?
>

Good idea.  I will wait several days and collect any more feedback and 
generate a new patch set.

David Daney

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

* Re: [PATCH 8/9] MIPS: Add a platform hook for swiotlb setup.
  2010-09-24 16:13     ` David Daney
@ 2010-09-24 16:32       ` Ralf Baechle
  0 siblings, 0 replies; 21+ messages in thread
From: Ralf Baechle @ 2010-09-24 16:32 UTC (permalink / raw)
  To: David Daney; +Cc: Sergei Shtylyov, linux-mips, linux-kernel

On Fri, Sep 24, 2010 at 09:13:54AM -0700, David Daney wrote:

> >>+#ifdef CONFIG_SWIOTLB
> >>+ plat_swiotlb_setup();
> >>+#endif
> >
> >We should avoid #ifdef's in function bodies. Why not defile an empty
> >'inline' in the header above if CONFIG_SWIOTLB is not defined?
> >
> 
> Good idea.  I will wait several days and collect any more feedback
> and generate a new patch set.

I'd also wait for a few more days so interested parties outside of the MIPS
world will have a chance to comment.

  Ralf

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

* Re: [PATCH 7/9] swiotlb: Make bounce buffer bounds non-static.
  2010-09-23 22:47 ` [PATCH 7/9] swiotlb: Make bounce buffer bounds non-static David Daney
@ 2010-09-27  5:20   ` FUJITA Tomonori
  2010-09-27 17:39     ` David Daney
  0 siblings, 1 reply; 21+ messages in thread
From: FUJITA Tomonori @ 2010-09-27  5:20 UTC (permalink / raw)
  To: ddaney
  Cc: linux-mips, ralf, linux-kernel, akpm, fujita.tomonori,
	konrad.wilk, mingo, andre.goddard

On Thu, 23 Sep 2010 15:47:31 -0700
David Daney <ddaney@caviumnetworks.com> wrote:

> Octeon PCI mapping has to be established to cover the bounce buffers,
> so it has to have access to the bounds.

Why can't you use swiotlb_init_with_tbl() instead?

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

* Re: [PATCH 5/9] MIPS: Convert DMA to use dma-mapping-common.h
  2010-09-23 22:38 ` [PATCH 5/9] MIPS: Convert DMA to use dma-mapping-common.h David Daney
  2010-09-24  1:03   ` [PATCH] MIPS: Remove plat_map_dma_mem_page() David Daney
@ 2010-09-27  5:30   ` FUJITA Tomonori
  2010-09-27 17:35     ` David Daney
  1 sibling, 1 reply; 21+ messages in thread
From: FUJITA Tomonori @ 2010-09-27  5:30 UTC (permalink / raw)
  To: ddaney; +Cc: linux-mips, ralf, linux-kernel

On Thu, 23 Sep 2010 15:38:12 -0700
David Daney <ddaney@caviumnetworks.com> wrote:

> Use asm-generic/dma-mapping-common.h to handle all DMA mapping
> operations and establish a default get_dma_ops() that forwards all
> operations to the existing code.
> 
> Augment dev_archdata to carry a pointer to the struct dma_map_ops,
> allowing DMA operations to be overridden on a per device basis.
> Currently this is never filled in, so the default dma_map_ops are
> used.  A follow-on patch sets this for Octeon PCI devices.
> 
> Also initialize the dma_debug system as it is now used if it is
> configured.
> 
> Signed-off-by: David Daney <ddaney@caviumnetworks.com>
> ---
>  arch/mips/Kconfig                   |    2 +
>  arch/mips/include/asm/device.h      |   15 +++-
>  arch/mips/include/asm/dma-mapping.h |  125 +++++++++++++++++--------
>  arch/mips/mm/dma-default.c          |  179 +++++++++++++---------------------
>  4 files changed, 172 insertions(+), 149 deletions(-)
> 
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index 6c33709..e68b89f 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -14,6 +14,8 @@ config MIPS
>  	select HAVE_KRETPROBES
>  	select RTC_LIB if !MACH_LOONGSON
>  	select GENERIC_ATOMIC64 if !64BIT
> +	select HAVE_DMA_ATTRS
> +	select HAVE_DMA_API_DEBUG
>  
>  mainmenu "Linux/MIPS Kernel Configuration"
>  
> diff --git a/arch/mips/include/asm/device.h b/arch/mips/include/asm/device.h
> index 06746c5..65bf274 100644
> --- a/arch/mips/include/asm/device.h
> +++ b/arch/mips/include/asm/device.h
> @@ -3,4 +3,17 @@
>   *
>   * This file is released under the GPLv2
>   */
> -#include <asm-generic/device.h>
> +#ifndef _ASM_MIPS_DEVICE_H
> +#define _ASM_MIPS_DEVICE_H
> +
> +struct mips_dma_map_ops;
> +
> +struct dev_archdata {
> +	/* DMA operations on that device */
> +	struct mips_dma_map_ops	*dma_ops;
> +};
> +
> +struct pdev_archdata {
> +};
> +
> +#endif /* _ASM_MIPS_DEVICE_H*/
> diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h
> index 18fbf7a..9a4c307 100644
> --- a/arch/mips/include/asm/dma-mapping.h
> +++ b/arch/mips/include/asm/dma-mapping.h
> @@ -5,51 +5,67 @@
>  #include <asm/cache.h>
>  #include <asm-generic/dma-coherent.h>
>  
> -void *dma_alloc_noncoherent(struct device *dev, size_t size,
> -			   dma_addr_t *dma_handle, gfp_t flag);
> +struct mips_dma_map_ops {
> +	struct dma_map_ops dma_map_ops;
> +	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);
> +};

The above code doesn't look great but we don't want to add phys_to_dma
and dma_to_phys to dma_map_ops struct, and these functions on MIPS
looks too complicated for ifdef. So I guess that we need to live with
the above code.

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

* Re: [PATCH 6/9] swiotlb: Declare swiotlb_init_with_default_size()
  2010-09-23 22:47 ` [PATCH 6/9] swiotlb: Declare swiotlb_init_with_default_size() David Daney
@ 2010-09-27 16:53   ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 21+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-09-27 16:53 UTC (permalink / raw)
  To: David Daney
  Cc: linux-mips, ralf, linux-kernel, Andrew Morton, FUJITA Tomonori,
	Ingo Molnar, Andre Goddard Rosa

On Thu, Sep 23, 2010 at 03:47:30PM -0700, David Daney wrote:
> It comes from swiotlb.c and must be called by external code, so declare it.
> 
> Signed-off-by: David Daney <ddaney@caviumnetworks.com>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Cc: Ingo Molnar <mingo@elte.hu>
> Cc: Andre Goddard Rosa <andre.goddard@gmail.com>
> ---
>  include/linux/swiotlb.h |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
> 
> diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
> index 8c0e349..dba51fe 100644
> --- a/include/linux/swiotlb.h
> +++ b/include/linux/swiotlb.h
> @@ -23,6 +23,7 @@ extern int swiotlb_force;
>  #define IO_TLB_SHIFT 11
>  
>  extern void swiotlb_init(int verbose);
> +extern void swiotlb_init_with_default_size(size_t, int);
>  extern void swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);

Just use the swiotlb_init_with_tbl. If you need an example of how it is utilized, take
a look at how swiotlb-xen.c does it.

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

* Re: [PATCH 5/9] MIPS: Convert DMA to use dma-mapping-common.h
  2010-09-27  5:30   ` [PATCH 5/9] MIPS: Convert DMA to use dma-mapping-common.h FUJITA Tomonori
@ 2010-09-27 17:35     ` David Daney
  2010-09-28  0:12       ` FUJITA Tomonori
  0 siblings, 1 reply; 21+ messages in thread
From: David Daney @ 2010-09-27 17:35 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: linux-mips, ralf, linux-kernel

On 09/26/2010 10:30 PM, FUJITA Tomonori wrote:
> On Thu, 23 Sep 2010 15:38:12 -0700
> David Daney<ddaney@caviumnetworks.com>  wrote:
>
>> Use asm-generic/dma-mapping-common.h to handle all DMA mapping
>> operations and establish a default get_dma_ops() that forwards all
>> operations to the existing code.
>>
>> Augment dev_archdata to carry a pointer to the struct dma_map_ops,
>> allowing DMA operations to be overridden on a per device basis.
>> Currently this is never filled in, so the default dma_map_ops are
>> used.  A follow-on patch sets this for Octeon PCI devices.
>>
>> Also initialize the dma_debug system as it is now used if it is
>> configured.
>>
>> Signed-off-by: David Daney<ddaney@caviumnetworks.com>
>> ---
>>   arch/mips/Kconfig                   |    2 +
>>   arch/mips/include/asm/device.h      |   15 +++-
>>   arch/mips/include/asm/dma-mapping.h |  125 +++++++++++++++++--------
>>   arch/mips/mm/dma-default.c          |  179 +++++++++++++---------------------
>>   4 files changed, 172 insertions(+), 149 deletions(-)
>>
>> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
>> index 6c33709..e68b89f 100644
>> --- a/arch/mips/Kconfig
>> +++ b/arch/mips/Kconfig
>> @@ -14,6 +14,8 @@ config MIPS
>>   	select HAVE_KRETPROBES
>>   	select RTC_LIB if !MACH_LOONGSON
>>   	select GENERIC_ATOMIC64 if !64BIT
>> +	select HAVE_DMA_ATTRS
>> +	select HAVE_DMA_API_DEBUG
>>
>>   mainmenu "Linux/MIPS Kernel Configuration"
>>
>> diff --git a/arch/mips/include/asm/device.h b/arch/mips/include/asm/device.h
>> index 06746c5..65bf274 100644
>> --- a/arch/mips/include/asm/device.h
>> +++ b/arch/mips/include/asm/device.h
>> @@ -3,4 +3,17 @@
>>    *
>>    * This file is released under the GPLv2
>>    */
>> -#include<asm-generic/device.h>
>> +#ifndef _ASM_MIPS_DEVICE_H
>> +#define _ASM_MIPS_DEVICE_H
>> +
>> +struct mips_dma_map_ops;
>> +
>> +struct dev_archdata {
>> +	/* DMA operations on that device */
>> +	struct mips_dma_map_ops	*dma_ops;
>> +};
>> +
>> +struct pdev_archdata {
>> +};
>> +
>> +#endif /* _ASM_MIPS_DEVICE_H*/
>> diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h
>> index 18fbf7a..9a4c307 100644
>> --- a/arch/mips/include/asm/dma-mapping.h
>> +++ b/arch/mips/include/asm/dma-mapping.h
>> @@ -5,51 +5,67 @@
>>   #include<asm/cache.h>
>>   #include<asm-generic/dma-coherent.h>
>>
>> -void *dma_alloc_noncoherent(struct device *dev, size_t size,
>> -			   dma_addr_t *dma_handle, gfp_t flag);
>> +struct mips_dma_map_ops {
>> +	struct dma_map_ops dma_map_ops;
>> +	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);
>> +};
>
> The above code doesn't look great but we don't want to add phys_to_dma
> and dma_to_phys to dma_map_ops struct, and these functions on MIPS
> looks too complicated for ifdef. So I guess that we need to live with
> the above code.
>

I think you have a point here.  I will attempt to move these two into a 
chip specific operations vector, and leave the more generic MIPS version 
with the simplified static definition.

Thanks,
David Daney

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

* Re: [PATCH 7/9] swiotlb: Make bounce buffer bounds non-static.
  2010-09-27  5:20   ` FUJITA Tomonori
@ 2010-09-27 17:39     ` David Daney
  0 siblings, 0 replies; 21+ messages in thread
From: David Daney @ 2010-09-27 17:39 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: linux-mips, ralf, linux-kernel, akpm, konrad.wilk, mingo,
	andre.goddard, konrad.wilk

On 09/26/2010 10:20 PM, FUJITA Tomonori wrote:
> On Thu, 23 Sep 2010 15:47:31 -0700
> David Daney<ddaney@caviumnetworks.com>  wrote:
>
>> Octeon PCI mapping has to be established to cover the bounce buffers,
>> so it has to have access to the bounds.
>
> Why can't you use swiotlb_init_with_tbl() instead?
>

Yes, as pointed out be several people, that would be better.

The swiotlb_init_with_tbl() didn't exist in earlier kernel versions and 
this simplification was missed when I forward ported the patch set.

By using this function, I think the entire patch set will be MIPS 
specific, making it unnecessary to touch the generic swiotlb code.

Thanks,
David Daney

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

* Re: [PATCH 5/9] MIPS: Convert DMA to use dma-mapping-common.h
  2010-09-27 17:35     ` David Daney
@ 2010-09-28  0:12       ` FUJITA Tomonori
  0 siblings, 0 replies; 21+ messages in thread
From: FUJITA Tomonori @ 2010-09-28  0:12 UTC (permalink / raw)
  To: ddaney; +Cc: fujita.tomonori, linux-mips, ralf, linux-kernel

On Mon, 27 Sep 2010 10:35:15 -0700
David Daney <ddaney@caviumnetworks.com> wrote:

> >> diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h
> >> index 18fbf7a..9a4c307 100644
> >> --- a/arch/mips/include/asm/dma-mapping.h
> >> +++ b/arch/mips/include/asm/dma-mapping.h
> >> @@ -5,51 +5,67 @@
> >>   #include<asm/cache.h>
> >>   #include<asm-generic/dma-coherent.h>
> >>
> >> -void *dma_alloc_noncoherent(struct device *dev, size_t size,
> >> -			   dma_addr_t *dma_handle, gfp_t flag);
> >> +struct mips_dma_map_ops {
> >> +	struct dma_map_ops dma_map_ops;
> >> +	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);
> >> +};
> >
> > The above code doesn't look great but we don't want to add phys_to_dma
> > and dma_to_phys to dma_map_ops struct, and these functions on MIPS
> > looks too complicated for ifdef. So I guess that we need to live with
> > the above code.
> >
> 
> I think you have a point here.  I will attempt to move these two into a 
> chip specific operations vector, and leave the more generic MIPS version 
> with the simplified static definition.

Yeah, that sounds a better (cleaner) approach.

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

end of thread, other threads:[~2010-09-28  0:12 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-09-23 22:38 [PATCH 0/9] MIPS: Use dma-mapping-common.h and use swiotlb for Octeon David Daney
2010-09-23 22:38 ` [PATCH 1/9] MIPS: Octeon: Set dma_masks for octeon_mgmt device David Daney
2010-09-23 22:38 ` [PATCH 2/9] MIPS: Allow MAX_DMA32_PFN to be overridden David Daney
2010-09-23 22:38 ` [PATCH 3/9] MIPS: Octeon: Adjust top of DMA32 zone David Daney
2010-09-23 22:38 ` [PATCH 4/9] MIPS: Octeon: Select ZONE_DMA32 David Daney
2010-09-23 22:38 ` [PATCH 5/9] MIPS: Convert DMA to use dma-mapping-common.h David Daney
2010-09-24  1:03   ` [PATCH] MIPS: Remove plat_map_dma_mem_page() David Daney
2010-09-27  5:30   ` [PATCH 5/9] MIPS: Convert DMA to use dma-mapping-common.h FUJITA Tomonori
2010-09-27 17:35     ` David Daney
2010-09-28  0:12       ` FUJITA Tomonori
2010-09-23 22:38 ` [PATCH 8/9] MIPS: Add a platform hook for swiotlb setup David Daney
2010-09-24 16:08   ` Sergei Shtylyov
2010-09-24 16:13     ` David Daney
2010-09-24 16:32       ` Ralf Baechle
2010-09-23 22:38 ` [PATCH 9/9] MIPS: Octeon: Rewrite DMA mapping functions David Daney
2010-09-24  1:06   ` [PATCH] MIPS: Octeon: Remove plat_map_dma_mem_page() David Daney
2010-09-23 22:47 ` [PATCH 6/9] swiotlb: Declare swiotlb_init_with_default_size() David Daney
2010-09-27 16:53   ` Konrad Rzeszutek Wilk
2010-09-23 22:47 ` [PATCH 7/9] swiotlb: Make bounce buffer bounds non-static David Daney
2010-09-27  5:20   ` FUJITA Tomonori
2010-09-27 17:39     ` David Daney

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox