linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] pseries/iommu bug-fixes and cleanups for dynamic dma windows
@ 2011-06-24 19:05 Nishanth Aravamudan
  2011-06-24 19:05 ` [PATCH 1/4] powerpc: override dma_get_required_mask by platform hook and ops Nishanth Aravamudan
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Nishanth Aravamudan @ 2011-06-24 19:05 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, linux-kernel

In my last submission, 5/8 wasn't sent to Ben, so he only picked up 1-4.
Re-sending 5-8, as such.

Milton Miller (4):
  powerpc: override dma_get_required_mask by platform hook and ops
  dma-mapping: add get_required_mask if arch overrides default
  powerpc: use the newly added get_required_mask dma_map_ops hook
  powerpc: tidy up dma_map_ops after adding new hook

Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-kernel@vger.kernel.org
Cc: benh@kernel.crashing.org

 arch/powerpc/include/asm/device.h       |    2 +
 arch/powerpc/include/asm/machdep.h      |    3 +-
 arch/powerpc/kernel/dma-iommu.c         |   28 ++++++++++++++-----
 arch/powerpc/kernel/dma-swiotlb.c       |   16 +++++++++++
 arch/powerpc/kernel/dma.c               |   44 ++++++++++++++++++++++++++-----
 arch/powerpc/kernel/ibmebus.c           |   22 ++++++++++-----
 arch/powerpc/kernel/vio.c               |   21 +++++++++-----
 arch/powerpc/platforms/cell/iommu.c     |   21 ++++++++++++++
 arch/powerpc/platforms/ps3/system-bus.c |    7 +++++
 arch/powerpc/platforms/pseries/iommu.c  |   27 +++++++++++++++++++
 include/linux/dma-mapping.h             |    3 ++
 11 files changed, 163 insertions(+), 31 deletions(-)

-- 
1.7.4.1

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

* [PATCH 1/4] powerpc: override dma_get_required_mask by platform hook and ops
  2011-06-24 19:05 [PATCH 0/4] pseries/iommu bug-fixes and cleanups for dynamic dma windows Nishanth Aravamudan
@ 2011-06-24 19:05 ` Nishanth Aravamudan
  2011-06-24 19:05 ` [PATCH 2/4] dma-mapping: add get_required_mask if arch overrides default Nishanth Aravamudan
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Nishanth Aravamudan @ 2011-06-24 19:05 UTC (permalink / raw)
  To: Milton Miller
  Cc: cbe-oss-dev, FUJITA Tomonori, Arnd Bergmann, Sonny Rao,
	devicetree-discuss, linux-kernel, Will Schmidt, Paul Mackerras,
	Anton Blanchard, H. Peter Anvin, Yinghai Lu, Nishanth Aravamudan,
	Andrew Morton, linuxppc-dev

From: Milton Miller <miltonm@bga.com>

The hook dma_get_required_mask is supposed to return the mask required
by the platform to operate efficently.  The generic version of
dma_get_required_mask in driver/base/platform.c returns a mask based
only on max_pfn.  However, this is likely too big for iommu systems
and could be too small for platforms that require a dma offset or have
a secondary window at a high offset.

Override the default, provide a hook in ppc_md used by pseries lpar and
cell, and provide the default answer based on memblock_end_of_DRAM(),
with hooks for get_dma_offset, and provide an implementation for iommu
that looks at the defined table size.  Coverting from the end address
to the required bit mask is based on the generic implementation.

The need for this was discovered when the qla2xxx driver switched to
64 bit dma then reverted to 32 bit when dma_get_required_mask said
32 bits was sufficient.

Signed-off-by: Milton Miller <miltonm@bga.com>
Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-kernel@vger.kernel.org
Cc: benh@kernel.crashing.org
---
 arch/powerpc/include/asm/dma-mapping.h |    3 ++
 arch/powerpc/include/asm/machdep.h     |    3 +-
 arch/powerpc/kernel/dma-iommu.c        |   13 ++++++++++
 arch/powerpc/kernel/dma.c              |   39 ++++++++++++++++++++++++++++++++
 arch/powerpc/platforms/cell/iommu.c    |   12 +++++++++
 arch/powerpc/platforms/pseries/iommu.c |   27 ++++++++++++++++++++++
 6 files changed, 96 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index dd70fac..8135e66 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -20,6 +20,8 @@
 
 #define DMA_ERROR_CODE		(~(dma_addr_t)0x0)
 
+#define ARCH_HAS_DMA_GET_REQUIRED_MASK
+
 /* Some dma direct funcs must be visible for use in other dma_ops */
 extern void *dma_direct_alloc_coherent(struct device *dev, size_t size,
 				       dma_addr_t *dma_handle, gfp_t flag);
@@ -69,6 +71,7 @@ static inline unsigned long device_to_mask(struct device *dev)
  */
 #ifdef CONFIG_PPC64
 extern struct dma_map_ops dma_iommu_ops;
+extern u64 dma_iommu_get_required_mask(struct device *dev);
 #endif
 extern struct dma_map_ops dma_direct_ops;
 
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 47cacdd..58fc216 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -85,8 +85,9 @@ struct machdep_calls {
 	void		(*pci_dma_dev_setup)(struct pci_dev *dev);
 	void		(*pci_dma_bus_setup)(struct pci_bus *bus);
 
-	/* Platform set_dma_mask override */
+	/* Platform set_dma_mask and dma_get_required_mask overrides */
 	int		(*dma_set_mask)(struct device *dev, u64 dma_mask);
+	u64		(*dma_get_required_mask)(struct device *dev);
 
 	int		(*probe)(void);
 	void		(*setup_arch)(void); /* Optional, may be NULL */
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
index e755415..1f2a711 100644
--- a/arch/powerpc/kernel/dma-iommu.c
+++ b/arch/powerpc/kernel/dma-iommu.c
@@ -90,6 +90,19 @@ static int dma_iommu_dma_supported(struct device *dev, u64 mask)
 		return 1;
 }
 
+u64 dma_iommu_get_required_mask(struct device *dev)
+{
+	struct iommu_table *tbl = get_iommu_table_base(dev);
+	u64 mask;
+	if (!tbl)
+		return 0;
+
+	mask = 1ULL < (fls_long(tbl->it_offset + tbl->it_size) - 1);
+	mask += mask - 1;
+
+	return mask;
+}
+
 struct dma_map_ops dma_iommu_ops = {
 	.alloc_coherent	= dma_iommu_alloc_coherent,
 	.free_coherent	= dma_iommu_free_coherent,
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index d238c08..97fe867 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -172,6 +172,45 @@ int dma_set_mask(struct device *dev, u64 dma_mask)
 }
 EXPORT_SYMBOL(dma_set_mask);
 
+u64 dma_get_required_mask(struct device *dev)
+{
+	struct dma_map_ops *dma_ops = get_dma_ops(dev);
+	u64 mask, end = 0;
+
+	if (ppc_md.dma_get_required_mask)
+		return ppc_md.dma_get_required_mask(dev);
+
+	if (unlikely(dma_ops == NULL))
+		return 0;
+
+#ifdef CONFIG_PPC64
+	else if (dma_ops == &dma_iommu_ops)
+		return dma_iommu_get_required_mask(dev);
+#endif
+#ifdef CONFIG_SWIOTLB
+	else if (dma_ops == &swiotlb_dma_ops) {
+		u64 max_direct_dma_addr = dev->archdata.max_direct_dma_addr;
+
+		end = memblock_end_of_DRAM();
+		if (max_direct_dma_addr && end > max_direct_dma_addr)
+			end = max_direct_dma_addr;
+		end += get_dma_offset(dev);
+	}
+#endif
+	else if (dma_ops == &dma_direct_ops)
+		end = memblock_end_of_DRAM() + get_dma_offset(dev);
+	else {
+		WARN_ONCE(1, "%s: unknown ops %p\n", __func__, dma_ops);
+		end = memblock_end_of_DRAM();
+	}
+
+	mask = 1ULL << (fls64(end) - 1);
+	mask += mask - 1;
+
+	return mask;
+}
+EXPORT_SYMBOL_GPL(dma_get_required_mask);
+
 static int __init dma_init(void)
 {
        dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 26a0671..5ef55f3 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -1159,6 +1159,17 @@ static int __init setup_iommu_fixed(char *str)
 }
 __setup("iommu_fixed=", setup_iommu_fixed);
 
+static u64 cell_dma_get_required_mask(struct device *dev)
+{
+	if (!dev->dma_mask)
+		return 0;
+
+	if (iommu_fixed_disabled && get_dma_ops(dev) == &dma_iommu_ops)
+		return dma_iommu_get_required_mask(dev);
+
+	return DMA_BIT_MASK(64);
+}
+
 static int __init cell_iommu_init(void)
 {
 	struct device_node *np;
@@ -1175,6 +1186,7 @@ static int __init cell_iommu_init(void)
 
 	/* Setup various ppc_md. callbacks */
 	ppc_md.pci_dma_dev_setup = cell_pci_dma_dev_setup;
+	ppc_md.dma_get_required_mask = cell_dma_get_required_mask;
 	ppc_md.tce_build = tce_build_cell;
 	ppc_md.tce_free = tce_free_cell;
 
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 01faab9..fe5eded 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -1077,12 +1077,38 @@ check_mask:
 	return 0;
 }
 
+static u64 dma_get_required_mask_pSeriesLP(struct device *dev)
+{
+	if (!dev->dma_mask)
+		return 0;
+
+	if (!disable_ddw && dev_is_pci(dev)) {
+		struct pci_dev *pdev = to_pci_dev(dev);
+		struct device_node *dn;
+
+		dn = pci_device_to_OF_node(pdev);
+
+		/* search upwards for ibm,dma-window */
+		for (; dn && PCI_DN(dn) && !PCI_DN(dn)->iommu_table;
+				dn = dn->parent)
+			if (of_get_property(dn, "ibm,dma-window", NULL))
+				break;
+		/* if there is a ibm,ddw-applicable property require 64 bits */
+		if (dn && PCI_DN(dn) &&
+				of_get_property(dn, "ibm,ddw-applicable", NULL))
+			return DMA_BIT_MASK(64);
+	}
+
+	return dma_iommu_get_required_mask(dev);
+}
+
 #else  /* CONFIG_PCI */
 #define pci_dma_bus_setup_pSeries	NULL
 #define pci_dma_dev_setup_pSeries	NULL
 #define pci_dma_bus_setup_pSeriesLP	NULL
 #define pci_dma_dev_setup_pSeriesLP	NULL
 #define dma_set_mask_pSeriesLP		NULL
+#define dma_get_required_mask_pSeriesLP	NULL
 #endif /* !CONFIG_PCI */
 
 static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
@@ -1186,6 +1212,7 @@ void iommu_init_early_pSeries(void)
 		ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP;
 		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP;
 		ppc_md.dma_set_mask = dma_set_mask_pSeriesLP;
+		ppc_md.dma_get_required_mask = dma_get_required_mask_pSeriesLP;
 	} else {
 		ppc_md.tce_build = tce_build_pSeries;
 		ppc_md.tce_free  = tce_free_pSeries;
-- 
1.7.4.1

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

* [PATCH 2/4] dma-mapping: add get_required_mask if arch overrides default
  2011-06-24 19:05 [PATCH 0/4] pseries/iommu bug-fixes and cleanups for dynamic dma windows Nishanth Aravamudan
  2011-06-24 19:05 ` [PATCH 1/4] powerpc: override dma_get_required_mask by platform hook and ops Nishanth Aravamudan
@ 2011-06-24 19:05 ` Nishanth Aravamudan
  2011-06-29  8:19   ` FUJITA Tomonori
  2011-06-24 19:05 ` [PATCH 3/4] powerpc: use the newly added get_required_mask dma_map_ops hook Nishanth Aravamudan
  2011-06-24 19:05 ` [PATCH 4/4] powerpc: tidy up dma_map_ops after adding new hook Nishanth Aravamudan
  3 siblings, 1 reply; 9+ messages in thread
From: Nishanth Aravamudan @ 2011-06-24 19:05 UTC (permalink / raw)
  To: Milton Miller; +Cc: Vinod Koul, Dan Williams, linuxppc-dev, linux-kernel

From: Milton Miller <miltonm@bga.com>

If an architecture sets ARCH_HAS_DMA_GET_REQUIRED_MASK and has settable
dma_map_ops, the required mask may change by the ops implementation.
For example, a system that always has an mmu inline may only require 32
bits while a swiotlb would desire bits to cover all of memory.

Therefore add the field if the architecture does not use the generic
definition of dma_get_required_mask. The first use will by by powerpc.
Note that this does add some dependency on the order in which files are
visible here.

Signed-off-by:  Milton Miller <miltonm@bga.com>
Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-kernel@vger.kernel.org
Cc: benh@kernel.crashing.org
---
 include/linux/dma-mapping.h |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index ba8319a..d0e023b 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -49,6 +49,9 @@ struct dma_map_ops {
 	int (*mapping_error)(struct device *dev, dma_addr_t dma_addr);
 	int (*dma_supported)(struct device *dev, u64 mask);
 	int (*set_dma_mask)(struct device *dev, u64 mask);
+#ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK
+	u64 (*get_required_mask)(struct device *dev);
+#endif
 	int is_phys;
 };
 
-- 
1.7.4.1

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

* [PATCH 3/4] powerpc: use the newly added get_required_mask dma_map_ops hook
  2011-06-24 19:05 [PATCH 0/4] pseries/iommu bug-fixes and cleanups for dynamic dma windows Nishanth Aravamudan
  2011-06-24 19:05 ` [PATCH 1/4] powerpc: override dma_get_required_mask by platform hook and ops Nishanth Aravamudan
  2011-06-24 19:05 ` [PATCH 2/4] dma-mapping: add get_required_mask if arch overrides default Nishanth Aravamudan
@ 2011-06-24 19:05 ` Nishanth Aravamudan
  2011-06-25 15:41   ` Geoff Levand
  2011-06-24 19:05 ` [PATCH 4/4] powerpc: tidy up dma_map_ops after adding new hook Nishanth Aravamudan
  3 siblings, 1 reply; 9+ messages in thread
From: Nishanth Aravamudan @ 2011-06-24 19:05 UTC (permalink / raw)
  To: Milton Miller
  Cc: cbe-oss-dev, Arnd Bergmann, Geoff Levand, Rafael J. Wysocki,
	linux-kernel, FUJITA Tomonori, Will Schmidt, Paul Mackerras,
	Anton Blanchard, H. Peter Anvin, Yinghai Lu, Nishanth Aravamudan,
	Andrew Morton, linuxppc-dev, David S. Miller

From: Milton Miller <miltonm@bga.com>

Now that the generic code has dma_map_ops set, instead of having a
messy ifdef & if block in the base dma_get_required_mask hook push
the computation into the dma ops.

If the ops fails to set the get_required_mask hook default to the
width of dma_addr_t.

This also corrects ibmbus ibmebus_dma_supported to require a 64
bit mask.  I doubt anything is checking or setting the dma mask on
that bus.

Signed-off-by: Milton Miller <miltonm@bga.com>
Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-kernel@vger.kernel.org
Cc: benh@kernel.crashing.org
---
 arch/powerpc/include/asm/device.h       |    2 +
 arch/powerpc/include/asm/dma-mapping.h  |    3 --
 arch/powerpc/kernel/dma-iommu.c         |    3 +-
 arch/powerpc/kernel/dma-swiotlb.c       |   16 ++++++++++++
 arch/powerpc/kernel/dma.c               |   41 ++++++++++++-------------------
 arch/powerpc/kernel/ibmebus.c           |    8 +++++-
 arch/powerpc/kernel/vio.c               |    7 ++++-
 arch/powerpc/platforms/cell/iommu.c     |   13 ++++++++-
 arch/powerpc/platforms/ps3/system-bus.c |    7 +++++
 arch/powerpc/platforms/pseries/iommu.c  |    2 +-
 10 files changed, 68 insertions(+), 34 deletions(-)

diff --git a/arch/powerpc/include/asm/device.h b/arch/powerpc/include/asm/device.h
index 16d25c0..d57c08a 100644
--- a/arch/powerpc/include/asm/device.h
+++ b/arch/powerpc/include/asm/device.h
@@ -37,4 +37,6 @@ struct pdev_archdata {
 	u64 dma_mask;
 };
 
+#define ARCH_HAS_DMA_GET_REQUIRED_MASK
+
 #endif /* _ASM_POWERPC_DEVICE_H */
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 8135e66..dd70fac 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -20,8 +20,6 @@
 
 #define DMA_ERROR_CODE		(~(dma_addr_t)0x0)
 
-#define ARCH_HAS_DMA_GET_REQUIRED_MASK
-
 /* Some dma direct funcs must be visible for use in other dma_ops */
 extern void *dma_direct_alloc_coherent(struct device *dev, size_t size,
 				       dma_addr_t *dma_handle, gfp_t flag);
@@ -71,7 +69,6 @@ static inline unsigned long device_to_mask(struct device *dev)
  */
 #ifdef CONFIG_PPC64
 extern struct dma_map_ops dma_iommu_ops;
-extern u64 dma_iommu_get_required_mask(struct device *dev);
 #endif
 extern struct dma_map_ops dma_direct_ops;
 
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
index 1f2a711..c1ad9db 100644
--- a/arch/powerpc/kernel/dma-iommu.c
+++ b/arch/powerpc/kernel/dma-iommu.c
@@ -90,7 +90,7 @@ static int dma_iommu_dma_supported(struct device *dev, u64 mask)
 		return 1;
 }
 
-u64 dma_iommu_get_required_mask(struct device *dev)
+static u64 dma_iommu_get_required_mask(struct device *dev)
 {
 	struct iommu_table *tbl = get_iommu_table_base(dev);
 	u64 mask;
@@ -111,5 +111,6 @@ struct dma_map_ops dma_iommu_ops = {
 	.dma_supported	= dma_iommu_dma_supported,
 	.map_page	= dma_iommu_map_page,
 	.unmap_page	= dma_iommu_unmap_page,
+	.get_required_mask	= dma_iommu_get_required_mask,
 };
 EXPORT_SYMBOL(dma_iommu_ops);
diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c
index 4295e0b..1ebc918 100644
--- a/arch/powerpc/kernel/dma-swiotlb.c
+++ b/arch/powerpc/kernel/dma-swiotlb.c
@@ -24,6 +24,21 @@
 
 unsigned int ppc_swiotlb_enable;
 
+static u64 swiotlb_powerpc_get_required(struct device *dev)
+{
+	u64 end, mask, max_direct_dma_addr = dev->archdata.max_direct_dma_addr;
+
+	end = memblock_end_of_DRAM();
+	if (max_direct_dma_addr && end > max_direct_dma_addr)
+		end = max_direct_dma_addr;
+	end += get_dma_offset(dev);
+
+	mask = 1ULL << (fls64(end) - 1);
+	mask += mask - 1;
+
+	return mask;
+}
+
 /*
  * At the moment, all platforms that use this code only require
  * swiotlb to be used if we're operating on HIGHMEM.  Since
@@ -44,6 +59,7 @@ struct dma_map_ops swiotlb_dma_ops = {
 	.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
 	.sync_sg_for_device = swiotlb_sync_sg_for_device,
 	.mapping_error = swiotlb_dma_mapping_error,
+	.get_required_mask = swiotlb_powerpc_get_required,
 };
 
 void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev)
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index 97fe867..df142d1 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -96,6 +96,18 @@ static int dma_direct_dma_supported(struct device *dev, u64 mask)
 #endif
 }
 
+static u64 dma_direct_get_required_mask(struct device *dev)
+{
+	u64 end, mask;
+
+	end = memblock_end_of_DRAM() + get_dma_offset(dev);
+
+	mask = 1ULL << (fls64(end) - 1);
+	mask += mask - 1;
+
+	return mask;
+}
+
 static inline dma_addr_t dma_direct_map_page(struct device *dev,
 					     struct page *page,
 					     unsigned long offset,
@@ -144,6 +156,7 @@ struct dma_map_ops dma_direct_ops = {
 	.dma_supported	= dma_direct_dma_supported,
 	.map_page	= dma_direct_map_page,
 	.unmap_page	= dma_direct_unmap_page,
+	.get_required_mask	= dma_direct_get_required_mask,
 #ifdef CONFIG_NOT_COHERENT_CACHE
 	.sync_single_for_cpu 		= dma_direct_sync_single,
 	.sync_single_for_device 	= dma_direct_sync_single,
@@ -175,7 +188,6 @@ EXPORT_SYMBOL(dma_set_mask);
 u64 dma_get_required_mask(struct device *dev)
 {
 	struct dma_map_ops *dma_ops = get_dma_ops(dev);
-	u64 mask, end = 0;
 
 	if (ppc_md.dma_get_required_mask)
 		return ppc_md.dma_get_required_mask(dev);
@@ -183,31 +195,10 @@ u64 dma_get_required_mask(struct device *dev)
 	if (unlikely(dma_ops == NULL))
 		return 0;
 
-#ifdef CONFIG_PPC64
-	else if (dma_ops == &dma_iommu_ops)
-		return dma_iommu_get_required_mask(dev);
-#endif
-#ifdef CONFIG_SWIOTLB
-	else if (dma_ops == &swiotlb_dma_ops) {
-		u64 max_direct_dma_addr = dev->archdata.max_direct_dma_addr;
-
-		end = memblock_end_of_DRAM();
-		if (max_direct_dma_addr && end > max_direct_dma_addr)
-			end = max_direct_dma_addr;
-		end += get_dma_offset(dev);
-	}
-#endif
-	else if (dma_ops == &dma_direct_ops)
-		end = memblock_end_of_DRAM() + get_dma_offset(dev);
-	else {
-		WARN_ONCE(1, "%s: unknown ops %p\n", __func__, dma_ops);
-		end = memblock_end_of_DRAM();
-	}
+	if (dma_ops->get_required_mask)
+		return dma_ops->get_required_mask(dev);
 
-	mask = 1ULL << (fls64(end) - 1);
-	mask += mask - 1;
-
-	return mask;
+	return DMA_BIT_MASK(8 * sizeof(dma_addr_t));
 }
 EXPORT_SYMBOL_GPL(dma_get_required_mask);
 
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 28581f1..90ef2a4 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -125,7 +125,12 @@ static void ibmebus_unmap_sg(struct device *dev,
 
 static int ibmebus_dma_supported(struct device *dev, u64 mask)
 {
-	return 1;
+	return mask == DMA_BIT_MASK(64);
+}
+
+static u64 ibmebus_dma_get_required_mask(struct device *dev)
+{
+	return DMA_BIT_MASK(64);
 }
 
 static struct dma_map_ops ibmebus_dma_ops = {
@@ -134,6 +139,7 @@ static struct dma_map_ops ibmebus_dma_ops = {
 	.map_sg         = ibmebus_map_sg,
 	.unmap_sg       = ibmebus_unmap_sg,
 	.dma_supported  = ibmebus_dma_supported,
+	.get_required_mask  = ibmebus_dma_get_required_mask,
 	.map_page       = ibmebus_map_page,
 	.unmap_page     = ibmebus_unmap_page,
 };
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 1b695fd..c049325 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -605,6 +605,11 @@ static int vio_dma_iommu_dma_supported(struct device *dev, u64 mask)
         return dma_iommu_ops.dma_supported(dev, mask);
 }
 
+static u64 vio_dma_get_required_mask(struct device *dev)
+{
+        return dma_iommu_ops.get_required_mask(dev);
+}
+
 struct dma_map_ops vio_dma_mapping_ops = {
 	.alloc_coherent = vio_dma_iommu_alloc_coherent,
 	.free_coherent  = vio_dma_iommu_free_coherent,
@@ -613,7 +618,7 @@ struct dma_map_ops vio_dma_mapping_ops = {
 	.map_page       = vio_dma_iommu_map_page,
 	.unmap_page     = vio_dma_iommu_unmap_page,
 	.dma_supported  = vio_dma_iommu_dma_supported,
-
+	.get_required_mask = vio_dma_get_required_mask,
 };
 
 /**
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 5ef55f3..fc46fca 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -1161,11 +1161,20 @@ __setup("iommu_fixed=", setup_iommu_fixed);
 
 static u64 cell_dma_get_required_mask(struct device *dev)
 {
+	struct dma_map_ops *dma_ops;
+
 	if (!dev->dma_mask)
 		return 0;
 
-	if (iommu_fixed_disabled && get_dma_ops(dev) == &dma_iommu_ops)
-		return dma_iommu_get_required_mask(dev);
+	if (!iommu_fixed_disabled &&
+			cell_iommu_get_fixed_address(dev) != OF_BAD_ADDR)
+		return DMA_BIT_MASK(64);
+
+	dma_ops = get_dma_ops(dev);
+	if (dma_ops->get_required_mask)
+		return dma_ops->get_required_mask(dev);
+
+	WARN_ONCE(1, "no get_required_mask in %p ops", dma_ops);
 
 	return DMA_BIT_MASK(64);
 }
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index 23083c3..688141c 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -695,12 +695,18 @@ static int ps3_dma_supported(struct device *_dev, u64 mask)
 	return mask >= DMA_BIT_MASK(32);
 }
 
+static u64 ps3_dma_get_required_mask(struct device *_dev)
+{
+	return DMA_BIT_MASK(32);
+}
+
 static struct dma_map_ops ps3_sb_dma_ops = {
 	.alloc_coherent = ps3_alloc_coherent,
 	.free_coherent = ps3_free_coherent,
 	.map_sg = ps3_sb_map_sg,
 	.unmap_sg = ps3_sb_unmap_sg,
 	.dma_supported = ps3_dma_supported,
+	.get_required_mask = ps3_dma_get_required_mask,
 	.map_page = ps3_sb_map_page,
 	.unmap_page = ps3_unmap_page,
 };
@@ -711,6 +717,7 @@ static struct dma_map_ops ps3_ioc0_dma_ops = {
 	.map_sg = ps3_ioc0_map_sg,
 	.unmap_sg = ps3_ioc0_unmap_sg,
 	.dma_supported = ps3_dma_supported,
+	.get_required_mask = ps3_dma_get_required_mask,
 	.map_page = ps3_ioc0_map_page,
 	.unmap_page = ps3_unmap_page,
 };
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index fe5eded..9f121a3 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -1099,7 +1099,7 @@ static u64 dma_get_required_mask_pSeriesLP(struct device *dev)
 			return DMA_BIT_MASK(64);
 	}
 
-	return dma_iommu_get_required_mask(dev);
+	return dma_iommu_ops.get_required_mask(dev);
 }
 
 #else  /* CONFIG_PCI */
-- 
1.7.4.1

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

* [PATCH 4/4] powerpc: tidy up dma_map_ops after adding new hook
  2011-06-24 19:05 [PATCH 0/4] pseries/iommu bug-fixes and cleanups for dynamic dma windows Nishanth Aravamudan
                   ` (2 preceding siblings ...)
  2011-06-24 19:05 ` [PATCH 3/4] powerpc: use the newly added get_required_mask dma_map_ops hook Nishanth Aravamudan
@ 2011-06-24 19:05 ` Nishanth Aravamudan
  3 siblings, 0 replies; 9+ messages in thread
From: Nishanth Aravamudan @ 2011-06-24 19:05 UTC (permalink / raw)
  To: Milton Miller
  Cc: Rafael J. Wysocki, linuxppc-dev, linux-kernel, Paul Mackerras,
	Anton Blanchard, H. Peter Anvin, Nishanth Aravamudan,
	Andrew Morton, Yinghai Lu

From: Milton Miller <miltonm@bga.com>

The new get_required_mask hook name is longer than many of but not all
of the prior ops.  Tidy the struct initializers to align the equal signs
using the local whitespace.

Signed-off-by: Milton Miller <miltonm@bga.com>
Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-kernel@vger.kernel.org
Cc: benh@kernel.crashing.org
---
 arch/powerpc/kernel/dma-iommu.c |   14 +++++++-------
 arch/powerpc/kernel/dma.c       |   16 ++++++++--------
 arch/powerpc/kernel/ibmebus.c   |   14 +++++++-------
 arch/powerpc/kernel/vio.c       |   14 +++++++-------
 4 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
index c1ad9db..6f04b9c 100644
--- a/arch/powerpc/kernel/dma-iommu.c
+++ b/arch/powerpc/kernel/dma-iommu.c
@@ -104,13 +104,13 @@ static u64 dma_iommu_get_required_mask(struct device *dev)
 }
 
 struct dma_map_ops dma_iommu_ops = {
-	.alloc_coherent	= dma_iommu_alloc_coherent,
-	.free_coherent	= dma_iommu_free_coherent,
-	.map_sg		= dma_iommu_map_sg,
-	.unmap_sg	= dma_iommu_unmap_sg,
-	.dma_supported	= dma_iommu_dma_supported,
-	.map_page	= dma_iommu_map_page,
-	.unmap_page	= dma_iommu_unmap_page,
+	.alloc_coherent		= dma_iommu_alloc_coherent,
+	.free_coherent		= dma_iommu_free_coherent,
+	.map_sg			= dma_iommu_map_sg,
+	.unmap_sg		= dma_iommu_unmap_sg,
+	.dma_supported		= dma_iommu_dma_supported,
+	.map_page		= dma_iommu_map_page,
+	.unmap_page		= dma_iommu_unmap_page,
 	.get_required_mask	= dma_iommu_get_required_mask,
 };
 EXPORT_SYMBOL(dma_iommu_ops);
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index df142d1..f94df52 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -149,14 +149,14 @@ static inline void dma_direct_sync_single(struct device *dev,
 #endif
 
 struct dma_map_ops dma_direct_ops = {
-	.alloc_coherent	= dma_direct_alloc_coherent,
-	.free_coherent	= dma_direct_free_coherent,
-	.map_sg		= dma_direct_map_sg,
-	.unmap_sg	= dma_direct_unmap_sg,
-	.dma_supported	= dma_direct_dma_supported,
-	.map_page	= dma_direct_map_page,
-	.unmap_page	= dma_direct_unmap_page,
-	.get_required_mask	= dma_direct_get_required_mask,
+	.alloc_coherent			= dma_direct_alloc_coherent,
+	.free_coherent			= dma_direct_free_coherent,
+	.map_sg				= dma_direct_map_sg,
+	.unmap_sg			= dma_direct_unmap_sg,
+	.dma_supported			= dma_direct_dma_supported,
+	.map_page			= dma_direct_map_page,
+	.unmap_page			= dma_direct_unmap_page,
+	.get_required_mask		= dma_direct_get_required_mask,
 #ifdef CONFIG_NOT_COHERENT_CACHE
 	.sync_single_for_cpu 		= dma_direct_sync_single,
 	.sync_single_for_device 	= dma_direct_sync_single,
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 90ef2a4..73110fb 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -134,14 +134,14 @@ static u64 ibmebus_dma_get_required_mask(struct device *dev)
 }
 
 static struct dma_map_ops ibmebus_dma_ops = {
-	.alloc_coherent = ibmebus_alloc_coherent,
-	.free_coherent  = ibmebus_free_coherent,
-	.map_sg         = ibmebus_map_sg,
-	.unmap_sg       = ibmebus_unmap_sg,
-	.dma_supported  = ibmebus_dma_supported,
+	.alloc_coherent     = ibmebus_alloc_coherent,
+	.free_coherent      = ibmebus_free_coherent,
+	.map_sg             = ibmebus_map_sg,
+	.unmap_sg           = ibmebus_unmap_sg,
+	.dma_supported      = ibmebus_dma_supported,
 	.get_required_mask  = ibmebus_dma_get_required_mask,
-	.map_page       = ibmebus_map_page,
-	.unmap_page     = ibmebus_unmap_page,
+	.map_page           = ibmebus_map_page,
+	.unmap_page         = ibmebus_unmap_page,
 };
 
 static int ibmebus_match_path(struct device *dev, void *data)
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index c049325..34d291d 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -611,13 +611,13 @@ static u64 vio_dma_get_required_mask(struct device *dev)
 }
 
 struct dma_map_ops vio_dma_mapping_ops = {
-	.alloc_coherent = vio_dma_iommu_alloc_coherent,
-	.free_coherent  = vio_dma_iommu_free_coherent,
-	.map_sg         = vio_dma_iommu_map_sg,
-	.unmap_sg       = vio_dma_iommu_unmap_sg,
-	.map_page       = vio_dma_iommu_map_page,
-	.unmap_page     = vio_dma_iommu_unmap_page,
-	.dma_supported  = vio_dma_iommu_dma_supported,
+	.alloc_coherent    = vio_dma_iommu_alloc_coherent,
+	.free_coherent     = vio_dma_iommu_free_coherent,
+	.map_sg            = vio_dma_iommu_map_sg,
+	.unmap_sg          = vio_dma_iommu_unmap_sg,
+	.map_page          = vio_dma_iommu_map_page,
+	.unmap_page        = vio_dma_iommu_unmap_page,
+	.dma_supported     = vio_dma_iommu_dma_supported,
 	.get_required_mask = vio_dma_get_required_mask,
 };
 
-- 
1.7.4.1

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

* Re: [PATCH 3/4] powerpc: use the newly added get_required_mask dma_map_ops hook
  2011-06-24 19:05 ` [PATCH 3/4] powerpc: use the newly added get_required_mask dma_map_ops hook Nishanth Aravamudan
@ 2011-06-25 15:41   ` Geoff Levand
  0 siblings, 0 replies; 9+ messages in thread
From: Geoff Levand @ 2011-06-25 15:41 UTC (permalink / raw)
  To: Nishanth Aravamudan
  Cc: cbe-oss-dev, Arnd Bergmann, Rafael J. Wysocki, linux-kernel,
	Milton Miller, FUJITA Tomonori, Paul Mackerras, Anton Blanchard,
	H. Peter Anvin, Yinghai Lu, Will Schmidt, Andrew Morton,
	linuxppc-dev, David S. Miller

[-- Attachment #1: Type: text/plain, Size: 389 bytes --]

On 06/24/2011 12:05 PM, Nishanth Aravamudan wrote:
> From: Milton Miller <miltonm@bga.com>
> 
> Now that the generic code has dma_map_ops set, instead of having a
> messy ifdef & if block in the base dma_get_required_mask hook push
> the computation into the dma ops.

>  arch/powerpc/platforms/ps3/system-bus.c |    7 +++++

Looks OK for PS3.

Acked-by Geoff Levand <geoff@infradead.org>

[-- Attachment #2: 0x2E141B16.asc --]
[-- Type: application/pgp-keys, Size: 9418 bytes --]

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

* Re: [PATCH 2/4] dma-mapping: add get_required_mask if arch overrides default
  2011-06-24 19:05 ` [PATCH 2/4] dma-mapping: add get_required_mask if arch overrides default Nishanth Aravamudan
@ 2011-06-29  8:19   ` FUJITA Tomonori
  2011-09-01  5:35     ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 9+ messages in thread
From: FUJITA Tomonori @ 2011-06-29  8:19 UTC (permalink / raw)
  To: nacc; +Cc: vinod.koul, linux-kernel, miltonm, dan.j.williams, linuxppc-dev

On Fri, 24 Jun 2011 12:05:23 -0700
Nishanth Aravamudan <nacc@us.ibm.com> wrote:

> From: Milton Miller <miltonm@bga.com>
> 
> If an architecture sets ARCH_HAS_DMA_GET_REQUIRED_MASK and has settable
> dma_map_ops, the required mask may change by the ops implementation.
> For example, a system that always has an mmu inline may only require 32
> bits while a swiotlb would desire bits to cover all of memory.
> 
> Therefore add the field if the architecture does not use the generic
> definition of dma_get_required_mask. The first use will by by powerpc.
> Note that this does add some dependency on the order in which files are
> visible here.
> 
> Signed-off-by:  Milton Miller <miltonm@bga.com>
> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: linux-kernel@vger.kernel.org
> Cc: benh@kernel.crashing.org
> ---
>  include/linux/dma-mapping.h |    3 +++
>  1 files changed, 3 insertions(+), 0 deletions(-)
> 
> diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
> index ba8319a..d0e023b 100644
> --- a/include/linux/dma-mapping.h
> +++ b/include/linux/dma-mapping.h
> @@ -49,6 +49,9 @@ struct dma_map_ops {
>  	int (*mapping_error)(struct device *dev, dma_addr_t dma_addr);
>  	int (*dma_supported)(struct device *dev, u64 mask);
>  	int (*set_dma_mask)(struct device *dev, u64 mask);
> +#ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK
> +	u64 (*get_required_mask)(struct device *dev);
> +#endif
>  	int is_phys;
>  };

If you add get_required_mask to dma_map_ops, we should clean up ia64
too and implement the generic proper version in
dma-mapping-common.h. Then we kill ARCH_HAS_DMA_GET_REQUIRED_MASK
ifdef hack. Otherwise, I don't think it makes sense to add this to
dma_map_ops.

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

* Re: [PATCH 2/4] dma-mapping: add get_required_mask if arch overrides default
  2011-06-29  8:19   ` FUJITA Tomonori
@ 2011-09-01  5:35     ` Benjamin Herrenschmidt
  2011-09-16 18:51       ` FUJITA Tomonori
  0 siblings, 1 reply; 9+ messages in thread
From: Benjamin Herrenschmidt @ 2011-09-01  5:35 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: vinod.koul, linux-kernel, miltonm, nacc, dan.j.williams, linuxppc-dev

On Wed, 2011-06-29 at 17:19 +0900, FUJITA Tomonori wrote:
> On Fri, 24 Jun 2011 12:05:23 -0700
> Nishanth Aravamudan <nacc@us.ibm.com> wrote:
> 
> > From: Milton Miller <miltonm@bga.com>
> > 
> > If an architecture sets ARCH_HAS_DMA_GET_REQUIRED_MASK and has settable
> > dma_map_ops, the required mask may change by the ops implementation.
> > For example, a system that always has an mmu inline may only require 32
> > bits while a swiotlb would desire bits to cover all of memory.
> > 
> > Therefore add the field if the architecture does not use the generic
> > definition of dma_get_required_mask. The first use will by by powerpc.
> > Note that this does add some dependency on the order in which files are
> > visible here.

 .../...

> If you add get_required_mask to dma_map_ops, we should clean up ia64
> too and implement the generic proper version in
> dma-mapping-common.h. Then we kill ARCH_HAS_DMA_GET_REQUIRED_MASK
> ifdef hack. Otherwise, I don't think it makes sense to add this to
> dma_map_ops.

In the meantime, can I have an ack so I can include this along with the
rest of Milton's patches ? It's been around for a while now :-)

I'm a bit late for producing a powerpc-next (due to travelling).

Cheers,
Ben.

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

* Re: [PATCH 2/4] dma-mapping: add get_required_mask if arch overrides default
  2011-09-01  5:35     ` Benjamin Herrenschmidt
@ 2011-09-16 18:51       ` FUJITA Tomonori
  0 siblings, 0 replies; 9+ messages in thread
From: FUJITA Tomonori @ 2011-09-16 18:51 UTC (permalink / raw)
  To: benh
  Cc: vinod.koul, linux-kernel, miltonm, fujita.tomonori, nacc,
	dan.j.williams, linuxppc-dev

Sorry for the late reply,

On Thu, 01 Sep 2011 15:35:11 +1000
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> On Wed, 2011-06-29 at 17:19 +0900, FUJITA Tomonori wrote:
> > On Fri, 24 Jun 2011 12:05:23 -0700
> > Nishanth Aravamudan <nacc@us.ibm.com> wrote:
> > 
> > > From: Milton Miller <miltonm@bga.com>
> > > 
> > > If an architecture sets ARCH_HAS_DMA_GET_REQUIRED_MASK and has settable
> > > dma_map_ops, the required mask may change by the ops implementation.
> > > For example, a system that always has an mmu inline may only require 32
> > > bits while a swiotlb would desire bits to cover all of memory.
> > > 
> > > Therefore add the field if the architecture does not use the generic
> > > definition of dma_get_required_mask. The first use will by by powerpc.
> > > Note that this does add some dependency on the order in which files are
> > > visible here.
> 
>  .../...
> 
> > If you add get_required_mask to dma_map_ops, we should clean up ia64
> > too and implement the generic proper version in
> > dma-mapping-common.h. Then we kill ARCH_HAS_DMA_GET_REQUIRED_MASK
> > ifdef hack. Otherwise, I don't think it makes sense to add this to
> > dma_map_ops.
> 
> In the meantime, can I have an ack so I can include this along with the
> rest of Milton's patches ? It's been around for a while now :-)

Sure, we can clean up this later.

Thanks,

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

end of thread, other threads:[~2011-09-16 19:00 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-24 19:05 [PATCH 0/4] pseries/iommu bug-fixes and cleanups for dynamic dma windows Nishanth Aravamudan
2011-06-24 19:05 ` [PATCH 1/4] powerpc: override dma_get_required_mask by platform hook and ops Nishanth Aravamudan
2011-06-24 19:05 ` [PATCH 2/4] dma-mapping: add get_required_mask if arch overrides default Nishanth Aravamudan
2011-06-29  8:19   ` FUJITA Tomonori
2011-09-01  5:35     ` Benjamin Herrenschmidt
2011-09-16 18:51       ` FUJITA Tomonori
2011-06-24 19:05 ` [PATCH 3/4] powerpc: use the newly added get_required_mask dma_map_ops hook Nishanth Aravamudan
2011-06-25 15:41   ` Geoff Levand
2011-06-24 19:05 ` [PATCH 4/4] powerpc: tidy up dma_map_ops after adding new hook Nishanth Aravamudan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).