All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v3 00/11] wii: add usb 2.0 support
@ 2010-03-07 12:11 Albert Herranz
  2010-03-07 12:11 ` [RFC PATCH v3 01/11] powerpc: add per-device dma coherent support Albert Herranz
                   ` (10 more replies)
  0 siblings, 11 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz

The following patch series adds USB 2.0 support for the Wii PowerPC
platform via the EHCI controller present in the "Hollywood" chipset
of the video game console.

v2 -> v3
- use per-device dma coherent support to allocate coherent MEM2 memory
- add support for SWIOTLB on NOT_COHERENT_CACHE PowerPC platforms
- use SWIOTLB instead of dmabounce to implement Wii MEM2 dma ops
- use v4 of the USB HCD_NO_COHERENT_MEM patch

Albert Herranz (11):
  powerpc: add per-device dma coherent support
  powerpc: add min_direct_dma_addr
  swiotbl: add back swiotlb_alloc_boot()
  swiotlb: support NOT_COHERENT_CACHE PowerPC platforms
  swiotlb: add swiotlb_set_default_size()
  USB: refactor unmap_urb_for_dma/map_urb_for_dma
  USB: add HCD_NO_COHERENT_MEM host controller driver flag
  wii: have generic dma coherent
  wii: add mem2 dma mapping ops
  wii: enable swiotlb
  wii: hollywood ehci controller support

 arch/ia64/include/asm/swiotlb.h              |   10 +
 arch/powerpc/boot/wii.c                      |   34 ++++
 arch/powerpc/include/asm/device.h            |    1 +
 arch/powerpc/include/asm/dma-mapping.h       |    3 +
 arch/powerpc/include/asm/swiotlb.h           |    3 +
 arch/powerpc/include/asm/wii.h               |   25 +++
 arch/powerpc/kernel/dma.c                    |    5 +
 arch/powerpc/platforms/embedded6xx/Kconfig   |    3 +
 arch/powerpc/platforms/embedded6xx/Makefile  |    2 +-
 arch/powerpc/platforms/embedded6xx/wii-dma.c |  255 ++++++++++++++++++++++++++
 arch/powerpc/platforms/embedded6xx/wii.c     |    2 +
 arch/x86/include/asm/swiotlb.h               |   10 +
 drivers/usb/core/buffer.c                    |   29 +++-
 drivers/usb/core/hcd.c                       |  233 ++++++++++++++++--------
 drivers/usb/core/hcd.h                       |   13 +-
 drivers/usb/host/Kconfig                     |    8 +
 drivers/usb/host/ehci-hcd.c                  |    5 +
 drivers/usb/host/ehci-hlwd.c                 |  233 +++++++++++++++++++++++
 drivers/usb/host/ehci.h                      |   23 +++
 include/linux/swiotlb.h                      |    4 +
 include/linux/usb.h                          |    5 +
 lib/swiotlb.c                                |   67 ++++++-
 22 files changed, 878 insertions(+), 95 deletions(-)
 create mode 100644 arch/powerpc/include/asm/wii.h
 create mode 100755 arch/powerpc/platforms/embedded6xx/wii-dma.c
 create mode 100644 drivers/usb/host/ehci-hlwd.c

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

* [RFC PATCH v3 01/11] powerpc: add per-device dma coherent support
  2010-03-07 12:11 [RFC PATCH v3 00/11] wii: add usb 2.0 support Albert Herranz
@ 2010-03-07 12:11 ` Albert Herranz
  2010-03-07 12:11 ` [RFC PATCH v3 02/11] powerpc: add min_direct_dma_addr Albert Herranz
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz

Use the generic per-device dma coherent allocator on powerpc.
This allows a driver to declare coherent memory area from where
a device can allocate coherent memory chunks.

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
---
 arch/powerpc/include/asm/dma-mapping.h |    1 +
 arch/powerpc/kernel/dma.c              |    5 +++++
 2 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 80a973b..18ecec8 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -17,6 +17,7 @@
 #include <linux/dma-debug.h>
 #include <asm/io.h>
 #include <asm/swiotlb.h>
+#include <asm-generic/dma-coherent.h>
 
 #define DMA_ERROR_CODE		(~(dma_addr_t)0x0)
 
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index 6215062..83d5232 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -27,6 +27,9 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size,
 {
 	void *ret;
 #ifdef CONFIG_NOT_COHERENT_CACHE
+	if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
+		return ret;
+
 	ret = __dma_alloc_coherent(dev, size, dma_handle, flag);
 	if (ret == NULL)
 		return NULL;
@@ -54,6 +57,8 @@ void dma_direct_free_coherent(struct device *dev, size_t size,
 			      void *vaddr, dma_addr_t dma_handle)
 {
 #ifdef CONFIG_NOT_COHERENT_CACHE
+	if (dma_release_from_coherent(dev, get_order(size), vaddr))
+		return;
 	__dma_free_coherent(size, vaddr);
 #else
 	free_pages((unsigned long)vaddr, get_order(size));
-- 
1.6.3.3

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

* [RFC PATCH v3 02/11] powerpc: add min_direct_dma_addr
  2010-03-07 12:11 [RFC PATCH v3 00/11] wii: add usb 2.0 support Albert Herranz
  2010-03-07 12:11 ` [RFC PATCH v3 01/11] powerpc: add per-device dma coherent support Albert Herranz
@ 2010-03-07 12:11 ` Albert Herranz
  2010-03-07 12:11   ` Albert Herranz
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz

This patch adds min_direct_dma_addr to struct dev_archdata.

min_direct_dma_addr can be used to define which is the minimum address
suitable for a DMA operation.
dma_capable() is updated to use this information in the SWIOTLB case.

This will be used later to support the Nintendo Wii video game console
which has limitations performing DMA to memory below 0x10000000 (MEM1).

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
---
 arch/powerpc/include/asm/device.h      |    1 +
 arch/powerpc/include/asm/dma-mapping.h |    2 ++
 2 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/device.h b/arch/powerpc/include/asm/device.h
index 6d94d27..23f0009 100644
--- a/arch/powerpc/include/asm/device.h
+++ b/arch/powerpc/include/asm/device.h
@@ -27,6 +27,7 @@ struct dev_archdata {
 
 #ifdef CONFIG_SWIOTLB
 	dma_addr_t		max_direct_dma_addr;
+	dma_addr_t		min_direct_dma_addr;
 #endif
 };
 
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 18ecec8..eda3ebe 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -193,6 +193,8 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
 
 	if (sd->max_direct_dma_addr && addr + size > sd->max_direct_dma_addr)
 		return 0;
+	if (sd->min_direct_dma_addr && addr < sd->min_direct_dma_addr)
+		return 0;
 #endif
 
 	if (!dev->dma_mask)
-- 
1.6.3.3

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

* [RFC PATCH v3 03/11] swiotbl: add back swiotlb_alloc_boot()
  2010-03-07 12:11 [RFC PATCH v3 00/11] wii: add usb 2.0 support Albert Herranz
  2010-03-07 12:11 ` [RFC PATCH v3 01/11] powerpc: add per-device dma coherent support Albert Herranz
@ 2010-03-07 12:11   ` Albert Herranz
  2010-03-07 12:11   ` Albert Herranz
                     ` (8 subsequent siblings)
  10 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz, linux-kernel, x86, linux-ia64

This patch makes swiotlb_alloc_boot() available again.

This weak function can be overloaded to modify slightly how the SWIOTLB
and the overflow areas are allocated during boot.

This will be used later to support the Nintendo Wii video game console,
which requires placing the SWIOTLB area above 0x10000000 (MEM2).

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
CC: linuxppc-dev@lists.ozlabs.org
CC: linux-kernel@vger.kernel.org
CC: x86@kernel.org
CC: linux-ia64@vger.kernel.org
---
 include/linux/swiotlb.h |    2 ++
 lib/swiotlb.c           |   10 ++++++++--
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index febedcf..3954228 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -24,6 +24,8 @@ extern int swiotlb_force;
 
 extern void swiotlb_init(int verbose);
 
+extern void *swiotlb_alloc_boot(size_t bytes, unsigned long nslabs);
+
 extern void
 *swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 			dma_addr_t *dma_handle, gfp_t flags);
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 437eedb..94db5df 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -117,6 +117,11 @@ setup_io_tlb_npages(char *str)
 __setup("swiotlb=", setup_io_tlb_npages);
 /* make io_tlb_overflow tunable too? */
 
+void * __weak __init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
+{
+	return alloc_bootmem_low_pages(size);
+}
+
 /* Note that this doesn't work with highmem page */
 static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
 				      volatile void *address)
@@ -158,7 +163,7 @@ 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);
+	io_tlb_start = swiotlb_alloc_boot(bytes, io_tlb_nslabs);
 	if (!io_tlb_start)
 		panic("Cannot allocate SWIOTLB buffer");
 	io_tlb_end = io_tlb_start + bytes;
@@ -177,7 +182,8 @@ swiotlb_init_with_default_size(size_t default_size, int verbose)
 	/*
 	 * Get the overflow emergency buffer
 	 */
-	io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow);
+	io_tlb_overflow_buffer = swiotlb_alloc_boot(io_tlb_overflow,
+						    io_tlb_nslabs);
 	if (!io_tlb_overflow_buffer)
 		panic("Cannot allocate SWIOTLB overflow buffer!\n");
 	if (verbose)
-- 
1.6.3.3


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

* [RFC PATCH v3 03/11] swiotbl: add back swiotlb_alloc_boot()
@ 2010-03-07 12:11   ` Albert Herranz
  0 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz, x86, linux-ia64, linux-kernel

This patch makes swiotlb_alloc_boot() available again.

This weak function can be overloaded to modify slightly how the SWIOTLB
and the overflow areas are allocated during boot.

This will be used later to support the Nintendo Wii video game console,
which requires placing the SWIOTLB area above 0x10000000 (MEM2).

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
CC: linuxppc-dev@lists.ozlabs.org
CC: linux-kernel@vger.kernel.org
CC: x86@kernel.org
CC: linux-ia64@vger.kernel.org
---
 include/linux/swiotlb.h |    2 ++
 lib/swiotlb.c           |   10 ++++++++--
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index febedcf..3954228 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -24,6 +24,8 @@ extern int swiotlb_force;
 
 extern void swiotlb_init(int verbose);
 
+extern void *swiotlb_alloc_boot(size_t bytes, unsigned long nslabs);
+
 extern void
 *swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 			dma_addr_t *dma_handle, gfp_t flags);
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 437eedb..94db5df 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -117,6 +117,11 @@ setup_io_tlb_npages(char *str)
 __setup("swiotlb=", setup_io_tlb_npages);
 /* make io_tlb_overflow tunable too? */
 
+void * __weak __init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
+{
+	return alloc_bootmem_low_pages(size);
+}
+
 /* Note that this doesn't work with highmem page */
 static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
 				      volatile void *address)
@@ -158,7 +163,7 @@ 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);
+	io_tlb_start = swiotlb_alloc_boot(bytes, io_tlb_nslabs);
 	if (!io_tlb_start)
 		panic("Cannot allocate SWIOTLB buffer");
 	io_tlb_end = io_tlb_start + bytes;
@@ -177,7 +182,8 @@ swiotlb_init_with_default_size(size_t default_size, int verbose)
 	/*
 	 * Get the overflow emergency buffer
 	 */
-	io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow);
+	io_tlb_overflow_buffer = swiotlb_alloc_boot(io_tlb_overflow,
+						    io_tlb_nslabs);
 	if (!io_tlb_overflow_buffer)
 		panic("Cannot allocate SWIOTLB overflow buffer!\n");
 	if (verbose)
-- 
1.6.3.3

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

* [RFC PATCH v3 03/11] swiotbl: add back swiotlb_alloc_boot()
@ 2010-03-07 12:11   ` Albert Herranz
  0 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz, linux-kernel, x86, linux-ia64

This patch makes swiotlb_alloc_boot() available again.

This weak function can be overloaded to modify slightly how the SWIOTLB
and the overflow areas are allocated during boot.

This will be used later to support the Nintendo Wii video game console,
which requires placing the SWIOTLB area above 0x10000000 (MEM2).

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
CC: linuxppc-dev@lists.ozlabs.org
CC: linux-kernel@vger.kernel.org
CC: x86@kernel.org
CC: linux-ia64@vger.kernel.org
---
 include/linux/swiotlb.h |    2 ++
 lib/swiotlb.c           |   10 ++++++++--
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index febedcf..3954228 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -24,6 +24,8 @@ extern int swiotlb_force;
 
 extern void swiotlb_init(int verbose);
 
+extern void *swiotlb_alloc_boot(size_t bytes, unsigned long nslabs);
+
 extern void
 *swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 			dma_addr_t *dma_handle, gfp_t flags);
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 437eedb..94db5df 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -117,6 +117,11 @@ setup_io_tlb_npages(char *str)
 __setup("swiotlb=", setup_io_tlb_npages);
 /* make io_tlb_overflow tunable too? */
 
+void * __weak __init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
+{
+	return alloc_bootmem_low_pages(size);
+}
+
 /* Note that this doesn't work with highmem page */
 static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
 				      volatile void *address)
@@ -158,7 +163,7 @@ 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);
+	io_tlb_start = swiotlb_alloc_boot(bytes, io_tlb_nslabs);
 	if (!io_tlb_start)
 		panic("Cannot allocate SWIOTLB buffer");
 	io_tlb_end = io_tlb_start + bytes;
@@ -177,7 +182,8 @@ swiotlb_init_with_default_size(size_t default_size, int verbose)
 	/*
 	 * Get the overflow emergency buffer
 	 */
-	io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow);
+	io_tlb_overflow_buffer = swiotlb_alloc_boot(io_tlb_overflow,
+						    io_tlb_nslabs);
 	if (!io_tlb_overflow_buffer)
 		panic("Cannot allocate SWIOTLB overflow buffer!\n");
 	if (verbose)
-- 
1.6.3.3


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

* [RFC PATCH v3 04/11] swiotlb: support NOT_COHERENT_CACHE PowerPC platforms
  2010-03-07 12:11 [RFC PATCH v3 00/11] wii: add usb 2.0 support Albert Herranz
  2010-03-07 12:11 ` [RFC PATCH v3 01/11] powerpc: add per-device dma coherent support Albert Herranz
@ 2010-03-07 12:11   ` Albert Herranz
  2010-03-07 12:11   ` Albert Herranz
                     ` (8 subsequent siblings)
  10 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz, linux-kernel, x86, linux-ia64

The current SWIOTLB code does not support NOT_COHERENT_CACHE platforms.
This patch adds support for NOT_COHERENT_CACHE platforms to SWIOTLB by
adding two platform specific functions swiotlb_dma_sync_page() and
swiotlb_dma_sync() which can be used to explicitly manage cache coherency.

On PowerPC these functions are mapped to their corresponding
__dma_sync_page() and __dma_sync() functions.
On other architectures using SWIOTLB these functions are optimized out.

This will be used later to support SWIOTLB on the Nintendo Wii video game
console.

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
CC: linuxppc-dev@lists.ozlabs.org
CC: linux-kernel@vger.kernel.org
CC: x86@kernel.org
CC: linux-ia64@vger.kernel.org
---
 arch/ia64/include/asm/swiotlb.h    |   10 ++++++++++
 arch/powerpc/include/asm/swiotlb.h |    3 +++
 arch/x86/include/asm/swiotlb.h     |   10 ++++++++++
 lib/swiotlb.c                      |   30 ++++++++++++++++++++++++------
 4 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/arch/ia64/include/asm/swiotlb.h b/arch/ia64/include/asm/swiotlb.h
index f0acde6..6722090 100644
--- a/arch/ia64/include/asm/swiotlb.h
+++ b/arch/ia64/include/asm/swiotlb.h
@@ -14,4 +14,14 @@ static inline void pci_swiotlb_init(void)
 }
 #endif
 
+static inline void swiotlb_dma_sync_page(struct page *page,
+					 unsigned long offset,
+					 size_t size, int direction)
+{
+}
+
+static inline void swiotlb_dma_sync(void *vaddr, size_t size, int direction)
+{
+}
+
 #endif /* ASM_IA64__SWIOTLB_H */
diff --git a/arch/powerpc/include/asm/swiotlb.h b/arch/powerpc/include/asm/swiotlb.h
index 8979d4c..603b343 100644
--- a/arch/powerpc/include/asm/swiotlb.h
+++ b/arch/powerpc/include/asm/swiotlb.h
@@ -22,4 +22,7 @@ int __init swiotlb_setup_bus_notifier(void);
 
 extern void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev);
 
+#define swiotlb_dma_sync_page __dma_sync_page
+#define swiotlb_dma_sync __dma_sync
+
 #endif /* __ASM_SWIOTLB_H */
diff --git a/arch/x86/include/asm/swiotlb.h b/arch/x86/include/asm/swiotlb.h
index 8085277..e5f6d9c 100644
--- a/arch/x86/include/asm/swiotlb.h
+++ b/arch/x86/include/asm/swiotlb.h
@@ -20,4 +20,14 @@ static inline void pci_swiotlb_init(void)
 
 static inline void dma_mark_clean(void *addr, size_t size) {}
 
+static inline void swiotlb_dma_sync_page(struct page *page,
+					 unsigned long offset,
+					 size_t size, int direction)
+{
+}
+
+static inline void swiotlb_dma_sync(void *vaddr, size_t size, int direction)
+{
+}
+
 #endif /* _ASM_X86_SWIOTLB_H */
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 94db5df..8f2dad9 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -346,10 +346,13 @@ static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
 			local_irq_save(flags);
 			buffer = kmap_atomic(pfn_to_page(pfn),
 					     KM_BOUNCE_READ);
-			if (dir == DMA_TO_DEVICE)
+			if (dir == DMA_TO_DEVICE) {
 				memcpy(dma_addr, buffer + offset, sz);
-			else
+				swiotlb_dma_sync(dma_addr, sz, dir);
+			} else {
+				swiotlb_dma_sync(dma_addr, sz, dir);
 				memcpy(buffer + offset, dma_addr, sz);
+			}
 			kunmap_atomic(buffer, KM_BOUNCE_READ);
 			local_irq_restore(flags);
 
@@ -359,10 +362,14 @@ static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
 			offset = 0;
 		}
 	} else {
-		if (dir == DMA_TO_DEVICE)
+		if (dir == DMA_TO_DEVICE) {
 			memcpy(dma_addr, phys_to_virt(phys), size);
-		else
+			swiotlb_dma_sync(dma_addr, size, dir);
+
+		} else {
+			swiotlb_dma_sync(dma_addr, size, dir);
 			memcpy(phys_to_virt(phys), dma_addr, size);
+		}
 	}
 }
 
@@ -542,6 +549,8 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size,
 	}
 }
 
+#ifndef CONFIG_NOT_COHERENT_CACHE
+
 void *
 swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 		       dma_addr_t *dma_handle, gfp_t flags)
@@ -606,6 +615,8 @@ swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
 }
 EXPORT_SYMBOL(swiotlb_free_coherent);
 
+#endif /* !CONFIG_NOT_COHERENT_CACHE */
+
 static void
 swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
 {
@@ -652,8 +663,10 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
 	 * we can safely return the device addr and not worry about bounce
 	 * buffering it.
 	 */
-	if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
+	if (dma_capable(dev, dev_addr, size) && !swiotlb_force) {
+		swiotlb_dma_sync_page(page, offset, size, dir);
 		return dev_addr;
+	}
 
 	/*
 	 * Oh well, have to allocate and map a bounce buffer.
@@ -739,6 +752,8 @@ swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
 		return;
 	}
 
+	swiotlb_dma_sync(phys_to_virt(paddr), size, dir);
+
 	if (dir != DMA_FROM_DEVICE)
 		return;
 
@@ -835,8 +850,11 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
 				return 0;
 			}
 			sg->dma_address = swiotlb_virt_to_bus(hwdev, map);
-		} else
+		} else {
+			swiotlb_dma_sync_page(sg_page(sg), sg->offset,
+					      sg->length, dir);
 			sg->dma_address = dev_addr;
+		}
 		sg->dma_length = sg->length;
 	}
 	return nelems;
-- 
1.6.3.3


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

* [RFC PATCH v3 04/11] swiotlb: support NOT_COHERENT_CACHE PowerPC platforms
@ 2010-03-07 12:11   ` Albert Herranz
  0 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz, x86, linux-ia64, linux-kernel

The current SWIOTLB code does not support NOT_COHERENT_CACHE platforms.
This patch adds support for NOT_COHERENT_CACHE platforms to SWIOTLB by
adding two platform specific functions swiotlb_dma_sync_page() and
swiotlb_dma_sync() which can be used to explicitly manage cache coherency.

On PowerPC these functions are mapped to their corresponding
__dma_sync_page() and __dma_sync() functions.
On other architectures using SWIOTLB these functions are optimized out.

This will be used later to support SWIOTLB on the Nintendo Wii video game
console.

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
CC: linuxppc-dev@lists.ozlabs.org
CC: linux-kernel@vger.kernel.org
CC: x86@kernel.org
CC: linux-ia64@vger.kernel.org
---
 arch/ia64/include/asm/swiotlb.h    |   10 ++++++++++
 arch/powerpc/include/asm/swiotlb.h |    3 +++
 arch/x86/include/asm/swiotlb.h     |   10 ++++++++++
 lib/swiotlb.c                      |   30 ++++++++++++++++++++++++------
 4 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/arch/ia64/include/asm/swiotlb.h b/arch/ia64/include/asm/swiotlb.h
index f0acde6..6722090 100644
--- a/arch/ia64/include/asm/swiotlb.h
+++ b/arch/ia64/include/asm/swiotlb.h
@@ -14,4 +14,14 @@ static inline void pci_swiotlb_init(void)
 }
 #endif
 
+static inline void swiotlb_dma_sync_page(struct page *page,
+					 unsigned long offset,
+					 size_t size, int direction)
+{
+}
+
+static inline void swiotlb_dma_sync(void *vaddr, size_t size, int direction)
+{
+}
+
 #endif /* ASM_IA64__SWIOTLB_H */
diff --git a/arch/powerpc/include/asm/swiotlb.h b/arch/powerpc/include/asm/swiotlb.h
index 8979d4c..603b343 100644
--- a/arch/powerpc/include/asm/swiotlb.h
+++ b/arch/powerpc/include/asm/swiotlb.h
@@ -22,4 +22,7 @@ int __init swiotlb_setup_bus_notifier(void);
 
 extern void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev);
 
+#define swiotlb_dma_sync_page __dma_sync_page
+#define swiotlb_dma_sync __dma_sync
+
 #endif /* __ASM_SWIOTLB_H */
diff --git a/arch/x86/include/asm/swiotlb.h b/arch/x86/include/asm/swiotlb.h
index 8085277..e5f6d9c 100644
--- a/arch/x86/include/asm/swiotlb.h
+++ b/arch/x86/include/asm/swiotlb.h
@@ -20,4 +20,14 @@ static inline void pci_swiotlb_init(void)
 
 static inline void dma_mark_clean(void *addr, size_t size) {}
 
+static inline void swiotlb_dma_sync_page(struct page *page,
+					 unsigned long offset,
+					 size_t size, int direction)
+{
+}
+
+static inline void swiotlb_dma_sync(void *vaddr, size_t size, int direction)
+{
+}
+
 #endif /* _ASM_X86_SWIOTLB_H */
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 94db5df..8f2dad9 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -346,10 +346,13 @@ static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
 			local_irq_save(flags);
 			buffer = kmap_atomic(pfn_to_page(pfn),
 					     KM_BOUNCE_READ);
-			if (dir == DMA_TO_DEVICE)
+			if (dir == DMA_TO_DEVICE) {
 				memcpy(dma_addr, buffer + offset, sz);
-			else
+				swiotlb_dma_sync(dma_addr, sz, dir);
+			} else {
+				swiotlb_dma_sync(dma_addr, sz, dir);
 				memcpy(buffer + offset, dma_addr, sz);
+			}
 			kunmap_atomic(buffer, KM_BOUNCE_READ);
 			local_irq_restore(flags);
 
@@ -359,10 +362,14 @@ static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
 			offset = 0;
 		}
 	} else {
-		if (dir == DMA_TO_DEVICE)
+		if (dir == DMA_TO_DEVICE) {
 			memcpy(dma_addr, phys_to_virt(phys), size);
-		else
+			swiotlb_dma_sync(dma_addr, size, dir);
+
+		} else {
+			swiotlb_dma_sync(dma_addr, size, dir);
 			memcpy(phys_to_virt(phys), dma_addr, size);
+		}
 	}
 }
 
@@ -542,6 +549,8 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size,
 	}
 }
 
+#ifndef CONFIG_NOT_COHERENT_CACHE
+
 void *
 swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 		       dma_addr_t *dma_handle, gfp_t flags)
@@ -606,6 +615,8 @@ swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
 }
 EXPORT_SYMBOL(swiotlb_free_coherent);
 
+#endif /* !CONFIG_NOT_COHERENT_CACHE */
+
 static void
 swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
 {
@@ -652,8 +663,10 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
 	 * we can safely return the device addr and not worry about bounce
 	 * buffering it.
 	 */
-	if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
+	if (dma_capable(dev, dev_addr, size) && !swiotlb_force) {
+		swiotlb_dma_sync_page(page, offset, size, dir);
 		return dev_addr;
+	}
 
 	/*
 	 * Oh well, have to allocate and map a bounce buffer.
@@ -739,6 +752,8 @@ swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
 		return;
 	}
 
+	swiotlb_dma_sync(phys_to_virt(paddr), size, dir);
+
 	if (dir != DMA_FROM_DEVICE)
 		return;
 
@@ -835,8 +850,11 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
 				return 0;
 			}
 			sg->dma_address = swiotlb_virt_to_bus(hwdev, map);
-		} else
+		} else {
+			swiotlb_dma_sync_page(sg_page(sg), sg->offset,
+					      sg->length, dir);
 			sg->dma_address = dev_addr;
+		}
 		sg->dma_length = sg->length;
 	}
 	return nelems;
-- 
1.6.3.3

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

* [RFC PATCH v3 04/11] swiotlb: support NOT_COHERENT_CACHE PowerPC platforms
@ 2010-03-07 12:11   ` Albert Herranz
  0 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz, linux-kernel, x86, linux-ia64

The current SWIOTLB code does not support NOT_COHERENT_CACHE platforms.
This patch adds support for NOT_COHERENT_CACHE platforms to SWIOTLB by
adding two platform specific functions swiotlb_dma_sync_page() and
swiotlb_dma_sync() which can be used to explicitly manage cache coherency.

On PowerPC these functions are mapped to their corresponding
__dma_sync_page() and __dma_sync() functions.
On other architectures using SWIOTLB these functions are optimized out.

This will be used later to support SWIOTLB on the Nintendo Wii video game
console.

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
CC: linuxppc-dev@lists.ozlabs.org
CC: linux-kernel@vger.kernel.org
CC: x86@kernel.org
CC: linux-ia64@vger.kernel.org
---
 arch/ia64/include/asm/swiotlb.h    |   10 ++++++++++
 arch/powerpc/include/asm/swiotlb.h |    3 +++
 arch/x86/include/asm/swiotlb.h     |   10 ++++++++++
 lib/swiotlb.c                      |   30 ++++++++++++++++++++++++------
 4 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/arch/ia64/include/asm/swiotlb.h b/arch/ia64/include/asm/swiotlb.h
index f0acde6..6722090 100644
--- a/arch/ia64/include/asm/swiotlb.h
+++ b/arch/ia64/include/asm/swiotlb.h
@@ -14,4 +14,14 @@ static inline void pci_swiotlb_init(void)
 }
 #endif
 
+static inline void swiotlb_dma_sync_page(struct page *page,
+					 unsigned long offset,
+					 size_t size, int direction)
+{
+}
+
+static inline void swiotlb_dma_sync(void *vaddr, size_t size, int direction)
+{
+}
+
 #endif /* ASM_IA64__SWIOTLB_H */
diff --git a/arch/powerpc/include/asm/swiotlb.h b/arch/powerpc/include/asm/swiotlb.h
index 8979d4c..603b343 100644
--- a/arch/powerpc/include/asm/swiotlb.h
+++ b/arch/powerpc/include/asm/swiotlb.h
@@ -22,4 +22,7 @@ int __init swiotlb_setup_bus_notifier(void);
 
 extern void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev);
 
+#define swiotlb_dma_sync_page __dma_sync_page
+#define swiotlb_dma_sync __dma_sync
+
 #endif /* __ASM_SWIOTLB_H */
diff --git a/arch/x86/include/asm/swiotlb.h b/arch/x86/include/asm/swiotlb.h
index 8085277..e5f6d9c 100644
--- a/arch/x86/include/asm/swiotlb.h
+++ b/arch/x86/include/asm/swiotlb.h
@@ -20,4 +20,14 @@ static inline void pci_swiotlb_init(void)
 
 static inline void dma_mark_clean(void *addr, size_t size) {}
 
+static inline void swiotlb_dma_sync_page(struct page *page,
+					 unsigned long offset,
+					 size_t size, int direction)
+{
+}
+
+static inline void swiotlb_dma_sync(void *vaddr, size_t size, int direction)
+{
+}
+
 #endif /* _ASM_X86_SWIOTLB_H */
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 94db5df..8f2dad9 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -346,10 +346,13 @@ static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
 			local_irq_save(flags);
 			buffer = kmap_atomic(pfn_to_page(pfn),
 					     KM_BOUNCE_READ);
-			if (dir = DMA_TO_DEVICE)
+			if (dir = DMA_TO_DEVICE) {
 				memcpy(dma_addr, buffer + offset, sz);
-			else
+				swiotlb_dma_sync(dma_addr, sz, dir);
+			} else {
+				swiotlb_dma_sync(dma_addr, sz, dir);
 				memcpy(buffer + offset, dma_addr, sz);
+			}
 			kunmap_atomic(buffer, KM_BOUNCE_READ);
 			local_irq_restore(flags);
 
@@ -359,10 +362,14 @@ static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
 			offset = 0;
 		}
 	} else {
-		if (dir = DMA_TO_DEVICE)
+		if (dir = DMA_TO_DEVICE) {
 			memcpy(dma_addr, phys_to_virt(phys), size);
-		else
+			swiotlb_dma_sync(dma_addr, size, dir);
+
+		} else {
+			swiotlb_dma_sync(dma_addr, size, dir);
 			memcpy(phys_to_virt(phys), dma_addr, size);
+		}
 	}
 }
 
@@ -542,6 +549,8 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size,
 	}
 }
 
+#ifndef CONFIG_NOT_COHERENT_CACHE
+
 void *
 swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 		       dma_addr_t *dma_handle, gfp_t flags)
@@ -606,6 +615,8 @@ swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
 }
 EXPORT_SYMBOL(swiotlb_free_coherent);
 
+#endif /* !CONFIG_NOT_COHERENT_CACHE */
+
 static void
 swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
 {
@@ -652,8 +663,10 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
 	 * we can safely return the device addr and not worry about bounce
 	 * buffering it.
 	 */
-	if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
+	if (dma_capable(dev, dev_addr, size) && !swiotlb_force) {
+		swiotlb_dma_sync_page(page, offset, size, dir);
 		return dev_addr;
+	}
 
 	/*
 	 * Oh well, have to allocate and map a bounce buffer.
@@ -739,6 +752,8 @@ swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
 		return;
 	}
 
+	swiotlb_dma_sync(phys_to_virt(paddr), size, dir);
+
 	if (dir != DMA_FROM_DEVICE)
 		return;
 
@@ -835,8 +850,11 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
 				return 0;
 			}
 			sg->dma_address = swiotlb_virt_to_bus(hwdev, map);
-		} else
+		} else {
+			swiotlb_dma_sync_page(sg_page(sg), sg->offset,
+					      sg->length, dir);
 			sg->dma_address = dev_addr;
+		}
 		sg->dma_length = sg->length;
 	}
 	return nelems;
-- 
1.6.3.3


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

* [RFC PATCH v3 05/11] swiotlb: add swiotlb_set_default_size()
  2010-03-07 12:11 [RFC PATCH v3 00/11] wii: add usb 2.0 support Albert Herranz
  2010-03-07 12:11 ` [RFC PATCH v3 01/11] powerpc: add per-device dma coherent support Albert Herranz
@ 2010-03-07 12:11   ` Albert Herranz
  2010-03-07 12:11   ` Albert Herranz
                     ` (8 subsequent siblings)
  10 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz, linux-kernel, x86, linux-ia64

The current SWIOTLB code uses a default of 64MB for the IO TLB area.
This size can be influenced using a kernel command line parameter "swiotlb".
Unfortunately, the parsing of the kernel command line is done _after_ the
swiotlb is initialized on some architectures.

This patch adds a new function swiotlb_set_default_size() which can be used
before swiotlb_init() to indicate the desired IO TLB area size in bytes.

This will be used later to implement a smaller IO TLB on the Nintendo Wii
video game console which just comes with 24MB + 64MB of RAM.

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
CC: linuxppc-dev@lists.ozlabs.org
CC: linux-kernel@vger.kernel.org
CC: x86@kernel.org
CC: linux-ia64@vger.kernel.org
---
 include/linux/swiotlb.h |    2 ++
 lib/swiotlb.c           |   27 ++++++++++++++++++++++++++-
 2 files changed, 28 insertions(+), 1 deletions(-)

diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 3954228..2af6a45 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -22,6 +22,8 @@ extern int swiotlb_force;
  */
 #define IO_TLB_SHIFT 11
 
+extern size_t __init swiotlb_set_default_size(size_t size);
+
 extern void swiotlb_init(int verbose);
 
 extern void *swiotlb_alloc_boot(size_t bytes, unsigned long nslabs);
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 8f2dad9..c99512d 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -73,6 +73,11 @@ static char *io_tlb_start, *io_tlb_end;
 static unsigned long io_tlb_nslabs;
 
 /*
+ * Default size for the IO TLB (64MB).
+ */
+static __initdata size_t io_tlb_default_size = 64 * (1<<20);
+
+/*
  * When the IOMMU overflows we return a fallback buffer. This sets the size.
  */
 static unsigned long io_tlb_overflow = 32*1024;
@@ -117,6 +122,26 @@ setup_io_tlb_npages(char *str)
 __setup("swiotlb=", setup_io_tlb_npages);
 /* make io_tlb_overflow tunable too? */
 
+/**
+ * swiotlb_set_default_size() - set the default size for the IO TLB
+ * @size:	size in bytes of the IO TLB
+ *
+ * A platform can use this function to change the default size of the
+ * IO TLB when the default of 64MB is not suitable.
+ * This function must be called before swiotlb_init().
+ *
+ * Note that on some platforms this is the only way to influence the
+ * size of the IO TLB, as the command line may be parsed _after_ the
+ * IO TLB is initialized.
+ */
+size_t __init swiotlb_set_default_size(size_t size)
+{
+	size_t previous_size = io_tlb_default_size;
+
+	io_tlb_default_size = size;
+	return previous_size;
+}
+
 void * __weak __init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
 {
 	return alloc_bootmem_low_pages(size);
@@ -193,7 +218,7 @@ swiotlb_init_with_default_size(size_t default_size, int verbose)
 void __init
 swiotlb_init(int verbose)
 {
-	swiotlb_init_with_default_size(64 * (1<<20), verbose);	/* default to 64MB */
+	swiotlb_init_with_default_size(io_tlb_default_size, verbose);
 }
 
 /*
-- 
1.6.3.3


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

* [RFC PATCH v3 05/11] swiotlb: add swiotlb_set_default_size()
@ 2010-03-07 12:11   ` Albert Herranz
  0 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz, x86, linux-ia64, linux-kernel

The current SWIOTLB code uses a default of 64MB for the IO TLB area.
This size can be influenced using a kernel command line parameter "swiotlb".
Unfortunately, the parsing of the kernel command line is done _after_ the
swiotlb is initialized on some architectures.

This patch adds a new function swiotlb_set_default_size() which can be used
before swiotlb_init() to indicate the desired IO TLB area size in bytes.

This will be used later to implement a smaller IO TLB on the Nintendo Wii
video game console which just comes with 24MB + 64MB of RAM.

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
CC: linuxppc-dev@lists.ozlabs.org
CC: linux-kernel@vger.kernel.org
CC: x86@kernel.org
CC: linux-ia64@vger.kernel.org
---
 include/linux/swiotlb.h |    2 ++
 lib/swiotlb.c           |   27 ++++++++++++++++++++++++++-
 2 files changed, 28 insertions(+), 1 deletions(-)

diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 3954228..2af6a45 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -22,6 +22,8 @@ extern int swiotlb_force;
  */
 #define IO_TLB_SHIFT 11
 
+extern size_t __init swiotlb_set_default_size(size_t size);
+
 extern void swiotlb_init(int verbose);
 
 extern void *swiotlb_alloc_boot(size_t bytes, unsigned long nslabs);
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 8f2dad9..c99512d 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -73,6 +73,11 @@ static char *io_tlb_start, *io_tlb_end;
 static unsigned long io_tlb_nslabs;
 
 /*
+ * Default size for the IO TLB (64MB).
+ */
+static __initdata size_t io_tlb_default_size = 64 * (1<<20);
+
+/*
  * When the IOMMU overflows we return a fallback buffer. This sets the size.
  */
 static unsigned long io_tlb_overflow = 32*1024;
@@ -117,6 +122,26 @@ setup_io_tlb_npages(char *str)
 __setup("swiotlb=", setup_io_tlb_npages);
 /* make io_tlb_overflow tunable too? */
 
+/**
+ * swiotlb_set_default_size() - set the default size for the IO TLB
+ * @size:	size in bytes of the IO TLB
+ *
+ * A platform can use this function to change the default size of the
+ * IO TLB when the default of 64MB is not suitable.
+ * This function must be called before swiotlb_init().
+ *
+ * Note that on some platforms this is the only way to influence the
+ * size of the IO TLB, as the command line may be parsed _after_ the
+ * IO TLB is initialized.
+ */
+size_t __init swiotlb_set_default_size(size_t size)
+{
+	size_t previous_size = io_tlb_default_size;
+
+	io_tlb_default_size = size;
+	return previous_size;
+}
+
 void * __weak __init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
 {
 	return alloc_bootmem_low_pages(size);
@@ -193,7 +218,7 @@ swiotlb_init_with_default_size(size_t default_size, int verbose)
 void __init
 swiotlb_init(int verbose)
 {
-	swiotlb_init_with_default_size(64 * (1<<20), verbose);	/* default to 64MB */
+	swiotlb_init_with_default_size(io_tlb_default_size, verbose);
 }
 
 /*
-- 
1.6.3.3

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

* [RFC PATCH v3 05/11] swiotlb: add swiotlb_set_default_size()
@ 2010-03-07 12:11   ` Albert Herranz
  0 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz, linux-kernel, x86, linux-ia64

The current SWIOTLB code uses a default of 64MB for the IO TLB area.
This size can be influenced using a kernel command line parameter "swiotlb".
Unfortunately, the parsing of the kernel command line is done _after_ the
swiotlb is initialized on some architectures.

This patch adds a new function swiotlb_set_default_size() which can be used
before swiotlb_init() to indicate the desired IO TLB area size in bytes.

This will be used later to implement a smaller IO TLB on the Nintendo Wii
video game console which just comes with 24MB + 64MB of RAM.

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
CC: linuxppc-dev@lists.ozlabs.org
CC: linux-kernel@vger.kernel.org
CC: x86@kernel.org
CC: linux-ia64@vger.kernel.org
---
 include/linux/swiotlb.h |    2 ++
 lib/swiotlb.c           |   27 ++++++++++++++++++++++++++-
 2 files changed, 28 insertions(+), 1 deletions(-)

diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 3954228..2af6a45 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -22,6 +22,8 @@ extern int swiotlb_force;
  */
 #define IO_TLB_SHIFT 11
 
+extern size_t __init swiotlb_set_default_size(size_t size);
+
 extern void swiotlb_init(int verbose);
 
 extern void *swiotlb_alloc_boot(size_t bytes, unsigned long nslabs);
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 8f2dad9..c99512d 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -73,6 +73,11 @@ static char *io_tlb_start, *io_tlb_end;
 static unsigned long io_tlb_nslabs;
 
 /*
+ * Default size for the IO TLB (64MB).
+ */
+static __initdata size_t io_tlb_default_size = 64 * (1<<20);
+
+/*
  * When the IOMMU overflows we return a fallback buffer. This sets the size.
  */
 static unsigned long io_tlb_overflow = 32*1024;
@@ -117,6 +122,26 @@ setup_io_tlb_npages(char *str)
 __setup("swiotlb=", setup_io_tlb_npages);
 /* make io_tlb_overflow tunable too? */
 
+/**
+ * swiotlb_set_default_size() - set the default size for the IO TLB
+ * @size:	size in bytes of the IO TLB
+ *
+ * A platform can use this function to change the default size of the
+ * IO TLB when the default of 64MB is not suitable.
+ * This function must be called before swiotlb_init().
+ *
+ * Note that on some platforms this is the only way to influence the
+ * size of the IO TLB, as the command line may be parsed _after_ the
+ * IO TLB is initialized.
+ */
+size_t __init swiotlb_set_default_size(size_t size)
+{
+	size_t previous_size = io_tlb_default_size;
+
+	io_tlb_default_size = size;
+	return previous_size;
+}
+
 void * __weak __init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
 {
 	return alloc_bootmem_low_pages(size);
@@ -193,7 +218,7 @@ swiotlb_init_with_default_size(size_t default_size, int verbose)
 void __init
 swiotlb_init(int verbose)
 {
-	swiotlb_init_with_default_size(64 * (1<<20), verbose);	/* default to 64MB */
+	swiotlb_init_with_default_size(io_tlb_default_size, verbose);
 }
 
 /*
-- 
1.6.3.3


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

* [RFC PATCH v3 06/11] USB: refactor unmap_urb_for_dma/map_urb_for_dma
  2010-03-07 12:11 [RFC PATCH v3 00/11] wii: add usb 2.0 support Albert Herranz
                   ` (4 preceding siblings ...)
  2010-03-07 12:11   ` Albert Herranz
@ 2010-03-07 12:11 ` Albert Herranz
  2010-03-07 12:11 ` [RFC PATCH v3 07/11] USB: add HCD_NO_COHERENT_MEM host controller driver flag Albert Herranz
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz

Split unmap_urb_for_dma() and map_urb_for_dma() into smaller pieces
to make the code easier to read and maintain.

This patch adds four new URB flags which are used by map_urb_for_dma()
to mark URBs with the exact method used to map the setup packet and/or the
transfer buffer.
These flags are checked too at unmap_urb_for_dma() time to determine how
to unmap the setup packet and/or the transfer buffer. The flags are cleared
when the actual unmap happens.

No functional change.

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
---
 drivers/usb/core/hcd.c |  211 +++++++++++++++++++++++++++++++-----------------
 include/linux/usb.h    |    5 +
 2 files changed, 143 insertions(+), 73 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 80995ef..44ad710 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1260,106 +1260,171 @@ static void hcd_free_coherent(struct usb_bus *bus, dma_addr_t *dma_handle,
 	*dma_handle = 0;
 }
 
-static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
-			   gfp_t mem_flags)
+static void unmap_urb_setup_packet(struct usb_hcd *hcd, struct urb *urb)
+{
+	if (urb->transfer_flags & URB_SETUP_DMA_MAPPED) {
+		urb->transfer_flags &= ~URB_SETUP_DMA_MAPPED;
+		dma_unmap_single(hcd->self.controller, urb->setup_dma,
+				 sizeof(struct usb_ctrlrequest),
+				 DMA_TO_DEVICE);
+	} else if (urb->transfer_flags & URB_SETUP_BOUNCE_MAPPED) {
+		/* bounce from "local" memory */
+		urb->transfer_flags &= ~URB_SETUP_BOUNCE_MAPPED;
+		hcd_free_coherent(urb->dev->bus, &urb->setup_dma,
+				  (void **)&urb->setup_packet,
+				  sizeof(struct usb_ctrlrequest),
+				  DMA_TO_DEVICE);
+	} else {
+		/* nothing to do for PIO-based controller requests */
+	}
+}
+
+static void unmap_urb_transfer_buffer(struct usb_hcd *hcd, struct urb *urb)
 {
 	enum dma_data_direction dir;
-	int ret = 0;
 
-	/* Map the URB's buffers for DMA access.
-	 * Lower level HCD code should use *_dma exclusively,
-	 * unless it uses pio or talks to another transport,
-	 * or uses the provided scatter gather list for bulk.
-	 */
+	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	if (urb->transfer_flags & URB_TRANSFER_DMA_MAPPED) {
+		urb->transfer_flags &= ~URB_TRANSFER_DMA_MAPPED;
+		dma_unmap_single(hcd->self.controller,
+				 urb->transfer_dma,
+				 urb->transfer_buffer_length,
+				 dir);
+	} else if (urb->transfer_flags & URB_TRANSFER_BOUNCE_MAPPED) {
+		/* bounce from "local" memory */
+		urb->transfer_flags &= ~URB_TRANSFER_BOUNCE_MAPPED;
+		hcd_free_coherent(urb->dev->bus, &urb->transfer_dma,
+				  &urb->transfer_buffer,
+				  urb->transfer_buffer_length,
+				  dir);
+	} else {
+		/* nothing to do for PIO-based controller requests */
+	}
+}
+
+static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
 	if (is_root_hub(urb->dev))
+		return;
+
+	unmap_urb_setup_packet(hcd, urb);
+	unmap_urb_transfer_buffer(hcd, urb);
+}
+
+static int urb_needs_setup_map(struct usb_hcd *hcd, struct urb *urb)
+{
+	/* setup mappings are required only for control requests */
+	if (!usb_endpoint_xfer_control(&urb->ep->desc))
+		return 0;
+
+	/* If the caller set URB_NO_SETUP_DMA_MAP then no mapping is needed */
+	if ((urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+		return 0;
+
+	return 1;
+}
+
+static int urb_needs_transfer_map(struct usb_hcd *hcd, struct urb *urb)
+{
+	/* don't need to map anything if there's nothing to map */
+	if (urb->transfer_buffer_length == 0)
 		return 0;
 
-	if (usb_endpoint_xfer_control(&urb->ep->desc)
-	    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
+	/* If the caller set URB_NO_SETUP_DMA_MAP then no mapping is needed */
+	if ((urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+		return 0;
+
+	return 1;
+}
+
+static int map_urb_setup_packet(struct usb_hcd *hcd, struct urb *urb,
+				gfp_t mem_flags)
+{
+	int ret;
+
+	if (urb_needs_setup_map(hcd, urb)) {
 		if (hcd->self.uses_dma) {
 			urb->setup_dma = dma_map_single(
-					hcd->self.controller,
-					urb->setup_packet,
-					sizeof(struct usb_ctrlrequest),
-					DMA_TO_DEVICE);
+						hcd->self.controller,
+						urb->setup_packet,
+						sizeof(struct usb_ctrlrequest),
+						DMA_TO_DEVICE);
 			if (dma_mapping_error(hcd->self.controller,
-						urb->setup_dma))
+					      urb->setup_dma))
 				return -EAGAIN;
-		} else if (hcd->driver->flags & HCD_LOCAL_MEM)
-			ret = hcd_alloc_coherent(
-					urb->dev->bus, mem_flags,
-					&urb->setup_dma,
-					(void **)&urb->setup_packet,
-					sizeof(struct usb_ctrlrequest),
-					DMA_TO_DEVICE);
+			urb->transfer_flags |= URB_SETUP_DMA_MAPPED;
+		} else if (hcd->driver->flags & HCD_LOCAL_MEM) {
+			/* bounce to "local" memory */
+			ret = hcd_alloc_coherent(urb->dev->bus, mem_flags,
+						 &urb->setup_dma,
+						 (void **)&urb->setup_packet,
+						 sizeof(struct usb_ctrlrequest),
+						 DMA_TO_DEVICE);
+			if (ret)
+				return ret;
+			urb->transfer_flags |= URB_SETUP_BOUNCE_MAPPED;
+		} else {
+			/* nothing to do for PIO-based controller requests */
+		}
 	}
+	return 0;
+}
+
+static int map_urb_transfer_buffer(struct usb_hcd *hcd, struct urb *urb,
+				   gfp_t mem_flags)
+{
+	enum dma_data_direction dir;
+	int ret;
 
 	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-	if (ret == 0 && urb->transfer_buffer_length != 0
-	    && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
+	if (urb_needs_transfer_map(hcd, urb)) {
 		if (hcd->self.uses_dma) {
 			urb->transfer_dma = dma_map_single (
-					hcd->self.controller,
-					urb->transfer_buffer,
-					urb->transfer_buffer_length,
-					dir);
+						hcd->self.controller,
+						urb->transfer_buffer,
+						urb->transfer_buffer_length,
+						dir);
 			if (dma_mapping_error(hcd->self.controller,
-						urb->transfer_dma))
+					      urb->transfer_dma))
 				return -EAGAIN;
+			urb->transfer_flags |= URB_TRANSFER_DMA_MAPPED;
 		} else if (hcd->driver->flags & HCD_LOCAL_MEM) {
-			ret = hcd_alloc_coherent(
-					urb->dev->bus, mem_flags,
-					&urb->transfer_dma,
-					&urb->transfer_buffer,
-					urb->transfer_buffer_length,
-					dir);
-
-			if (ret && usb_endpoint_xfer_control(&urb->ep->desc)
-			    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
-				hcd_free_coherent(urb->dev->bus,
-					&urb->setup_dma,
-					(void **)&urb->setup_packet,
-					sizeof(struct usb_ctrlrequest),
-					DMA_TO_DEVICE);
+			/* bounce to "local" memory */
+			ret = hcd_alloc_coherent(urb->dev->bus, mem_flags,
+						 &urb->transfer_dma,
+						 &urb->transfer_buffer,
+						 urb->transfer_buffer_length,
+						 dir);
+			if (ret)
+				return ret;
+			urb->transfer_flags |= URB_TRANSFER_BOUNCE_MAPPED;
+		} else {
+			/* nothing to do for PIO-based controller requests */
 		}
 	}
-	return ret;
+	return 0;
 }
 
-static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+			   gfp_t mem_flags)
 {
-	enum dma_data_direction dir;
+	int error;
 
+	/* Map the URB's buffers for DMA access.
+	 * Lower level HCD code should use *_dma exclusively,
+	 * unless it uses pio or talks to another transport,
+	 * or uses the provided scatter gather list for bulk.
+	 */
 	if (is_root_hub(urb->dev))
-		return;
-
-	if (usb_endpoint_xfer_control(&urb->ep->desc)
-	    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
-		if (hcd->self.uses_dma)
-			dma_unmap_single(hcd->self.controller, urb->setup_dma,
-					sizeof(struct usb_ctrlrequest),
-					DMA_TO_DEVICE);
-		else if (hcd->driver->flags & HCD_LOCAL_MEM)
-			hcd_free_coherent(urb->dev->bus, &urb->setup_dma,
-					(void **)&urb->setup_packet,
-					sizeof(struct usb_ctrlrequest),
-					DMA_TO_DEVICE);
-	}
+		return 0;
 
-	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-	if (urb->transfer_buffer_length != 0
-	    && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
-		if (hcd->self.uses_dma)
-			dma_unmap_single(hcd->self.controller,
-					urb->transfer_dma,
-					urb->transfer_buffer_length,
-					dir);
-		else if (hcd->driver->flags & HCD_LOCAL_MEM)
-			hcd_free_coherent(urb->dev->bus, &urb->transfer_dma,
-					&urb->transfer_buffer,
-					urb->transfer_buffer_length,
-					dir);
+	error = map_urb_setup_packet(hcd, urb, mem_flags);
+	if (!error) {
+		error = map_urb_transfer_buffer(hcd, urb, mem_flags);
+		if (error)
+			unmap_urb_setup_packet(hcd, urb);
 	}
+	return error;
 }
 
 /*-------------------------------------------------------------------------*/
diff --git a/include/linux/usb.h b/include/linux/usb.h
index d7ace1b..5e99cbd 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -985,6 +985,11 @@ extern int usb_disabled(void);
 #define URB_DIR_OUT		0
 #define URB_DIR_MASK		URB_DIR_IN
 
+#define URB_SETUP_DMA_MAPPED		0x1000 /* via dma_map_single */
+#define URB_SETUP_BOUNCE_MAPPED		0x2000 /* via hcd_alloc_coherent */
+#define URB_TRANSFER_DMA_MAPPED		0x4000 /* via dma_map_single */
+#define URB_TRANSFER_BOUNCE_MAPPED	0x8000 /* via hcd_alloc_coherent */
+
 struct usb_iso_packet_descriptor {
 	unsigned int offset;
 	unsigned int length;		/* expected length */
-- 
1.6.3.3

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

* [RFC PATCH v3 07/11] USB: add HCD_NO_COHERENT_MEM host controller driver flag
  2010-03-07 12:11 [RFC PATCH v3 00/11] wii: add usb 2.0 support Albert Herranz
                   ` (5 preceding siblings ...)
  2010-03-07 12:11 ` [RFC PATCH v3 06/11] USB: refactor unmap_urb_for_dma/map_urb_for_dma Albert Herranz
@ 2010-03-07 12:11 ` Albert Herranz
  2010-03-07 12:11 ` [RFC PATCH v3 08/11] wii: have generic dma coherent Albert Herranz
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz

The HCD_NO_COHERENT_MEM USB host controller driver flag can be enabled
to instruct the USB stack to avoid allocating coherent memory for USB
buffers.

This flag is useful to overcome some esoteric memory access restrictions
found in some platforms.
For example, the Nintendo Wii video game console is a NOT_COHERENT_CACHE
platform that is unable to safely perform non-32 bit uncached writes
to RAM because the byte enables are not connected to the bus.
Thus, in that platform, "coherent" DMA buffers cannot be directly used
by the kernel code unless it guarantees that all write accesses
to said buffers are done in 32 bit chunks (which is not the case in the
USB subsystem).

To avoid this unwanted behaviour HCD_NO_COHERENT_MEM can be enabled at
the HCD controller, causing USB buffer allocations to be satisfied from
normal kernel memory. In this case, the USB stack will make sure that
the buffers get properly mapped/unmapped for DMA transfers using the DMA
streaming mapping API.

Note that other parts of the USB stack may also use coherent memory,
like for example the hardware descriptors used in the EHCI controllers.
This needs to be checked and addressed separately. In the EHCI example,
hardware descriptors are accessed in 32-bit (or 64-bit) chunks, causing
no problems in the described scenario.

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
---
 drivers/usb/core/buffer.c |   29 +++++++++++++++++++++++------
 drivers/usb/core/hcd.c    |   32 +++++++++++++++++++++++++++-----
 drivers/usb/core/hcd.h    |   13 +++++++------
 3 files changed, 57 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index 3ba2fff..10cd11d 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -36,6 +36,26 @@ static const size_t	pool_max [HCD_BUFFER_POOLS] = {
 
 /* SETUP primitives */
 
+static inline int hcd_uses_pio(struct usb_hcd *hcd)
+{
+	if ((!hcd->self.controller->dma_mask &&
+	    !(hcd->driver->flags & HCD_LOCAL_MEM)))
+		return 1;
+	return 0;
+}
+
+static inline int hcd_needs_non_dma_mem(struct usb_hcd *hcd)
+{
+	/*
+	 * PIO-based and HCD_NO_COHERENT_MEM-based controllers use
+	 * normal kernel memory.
+	 * The rest want DMA memory.
+	 */
+	if (hcd_uses_pio(hcd) || (hcd->driver->flags & HCD_NO_COHERENT_MEM))
+		return 1;
+	return 0;
+}
+
 /**
  * hcd_buffer_create - initialize buffer pools
  * @hcd: the bus whose buffer pools are to be initialized
@@ -53,8 +73,7 @@ int hcd_buffer_create(struct usb_hcd *hcd)
 	char		name[16];
 	int 		i, size;
 
-	if (!hcd->self.controller->dma_mask &&
-	    !(hcd->driver->flags & HCD_LOCAL_MEM))
+	if (hcd_needs_non_dma_mem(hcd))
 		return 0;
 
 	for (i = 0; i < HCD_BUFFER_POOLS; i++) {
@@ -109,8 +128,7 @@ void *hcd_buffer_alloc(
 	int 			i;
 
 	/* some USB hosts just use PIO */
-	if (!bus->controller->dma_mask &&
-	    !(hcd->driver->flags & HCD_LOCAL_MEM)) {
+	if (hcd_needs_non_dma_mem(hcd)) {
 		*dma = ~(dma_addr_t) 0;
 		return kmalloc(size, mem_flags);
 	}
@@ -135,8 +153,7 @@ void hcd_buffer_free(
 	if (!addr)
 		return;
 
-	if (!bus->controller->dma_mask &&
-	    !(hcd->driver->flags & HCD_LOCAL_MEM)) {
+	if (hcd_needs_non_dma_mem(hcd)) {
 		kfree(addr);
 		return;
 	}
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 44ad710..174853a 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1316,9 +1316,19 @@ static int urb_needs_setup_map(struct usb_hcd *hcd, struct urb *urb)
 	/* setup mappings are required only for control requests */
 	if (!usb_endpoint_xfer_control(&urb->ep->desc))
 		return 0;
-
-	/* If the caller set URB_NO_SETUP_DMA_MAP then no mapping is needed */
-	if ((urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+	/*
+	 * Setup packets are 8 bytes long and don't use scatter/gather.
+	 *
+	 * If the caller sets URB_NO_SETUP_DMA_MAP and urb->setup_dma
+	 * contains a valid DMA handle then it is already mapped, except
+	 * if the controller can't use coherent memory (HCD_NO_COHERENT_MEM).
+	 *
+	 * urb->setup_dma is set to ~0 when allocating USB buffers for
+	 * PIO-based or HCD_NO_COHERENT_MEM-based controllers.
+	 */
+	if ((urb->transfer_flags & URB_NO_SETUP_DMA_MAP) &&
+	    urb->setup_dma != ~(dma_addr_t)0 &&
+	    !(hcd->driver->flags & HCD_NO_COHERENT_MEM))
 		return 0;
 
 	return 1;
@@ -1330,8 +1340,20 @@ static int urb_needs_transfer_map(struct usb_hcd *hcd, struct urb *urb)
 	if (urb->transfer_buffer_length == 0)
 		return 0;
 
-	/* If the caller set URB_NO_SETUP_DMA_MAP then no mapping is needed */
-	if ((urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+	/* if this is a scatter/gather request, it should be already mapped */
+	if (urb->num_sgs > 0)
+		return 0;
+	/*
+	 * If the caller sets URB_NO_TRANSFER_DMA_MAP and urb->transfer_dma
+	 * contains a valid DMA handle then it is already mapped, except
+	 * if the controller can't use coherent memory (HCD_NO_COHERENT_MEM).
+	 *
+	 * urb->transfer_dma is set to ~0 when allocating USB buffers for
+	 * PIO-based or HCD_NO_COHERENT_MEM-based controllers.
+	 */
+	if ((urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) &&
+	    urb->transfer_dma != ~(dma_addr_t)0 &&
+	    !(hcd->driver->flags & HCD_NO_COHERENT_MEM))
 		return 0;
 
 	return 1;
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index bbe2b92..cde42f3 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -183,12 +183,13 @@ struct hc_driver {
 	irqreturn_t	(*irq) (struct usb_hcd *hcd);
 
 	int	flags;
-#define	HCD_MEMORY	0x0001		/* HC regs use memory (else I/O) */
-#define	HCD_LOCAL_MEM	0x0002		/* HC needs local memory */
-#define	HCD_USB11	0x0010		/* USB 1.1 */
-#define	HCD_USB2	0x0020		/* USB 2.0 */
-#define	HCD_USB3	0x0040		/* USB 3.0 */
-#define	HCD_MASK	0x0070
+#define	HCD_MEMORY		0x0001	/* HC regs use memory (else I/O) */
+#define	HCD_LOCAL_MEM		0x0002	/* HC needs local memory */
+#define	HCD_NO_COHERENT_MEM	0x0004	/* HC avoids use of "coherent" mem */
+#define	HCD_USB11		0x0010	/* USB 1.1 */
+#define	HCD_USB2		0x0020	/* USB 2.0 */
+#define	HCD_USB3		0x0040	/* USB 3.0 */
+#define	HCD_MASK		0x0070
 
 	/* called to init HCD and root hub */
 	int	(*reset) (struct usb_hcd *hcd);
-- 
1.6.3.3

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

* [RFC PATCH v3 08/11] wii: have generic dma coherent
  2010-03-07 12:11 [RFC PATCH v3 00/11] wii: add usb 2.0 support Albert Herranz
                   ` (6 preceding siblings ...)
  2010-03-07 12:11 ` [RFC PATCH v3 07/11] USB: add HCD_NO_COHERENT_MEM host controller driver flag Albert Herranz
@ 2010-03-07 12:11 ` Albert Herranz
  2010-03-07 12:11 ` [RFC PATCH v3 09/11] wii: add mem2 dma mapping ops Albert Herranz
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz

Let the Nintendo Wii gaming console use per-device dma coherent allocations.
This will be used later by some of its drivers.

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
---
 arch/powerpc/platforms/embedded6xx/Kconfig |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index 524d971..fe77ab2 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -119,6 +119,7 @@ config WII
 	bool "Nintendo-Wii"
 	depends on EMBEDDED6xx
 	select GAMECUBE_COMMON
+	select HAVE_GENERIC_DMA_COHERENT
 	help
 	  Select WII if configuring for the Nintendo Wii.
 	  More information at: <http://gc-linux.sourceforge.net/>
-- 
1.6.3.3

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

* [RFC PATCH v3 09/11] wii: add mem2 dma mapping ops
  2010-03-07 12:11 [RFC PATCH v3 00/11] wii: add usb 2.0 support Albert Herranz
                   ` (7 preceding siblings ...)
  2010-03-07 12:11 ` [RFC PATCH v3 08/11] wii: have generic dma coherent Albert Herranz
@ 2010-03-07 12:11 ` Albert Herranz
  2010-03-07 12:11 ` [RFC PATCH v3 10/11] wii: enable swiotlb Albert Herranz
  2010-03-07 12:11 ` [RFC PATCH v3 11/11] wii: hollywood ehci controller support Albert Herranz
  10 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz

Some of the devices in the "Hollywood" chipset of the Nintendo Wii video
game console have restrictions performing DMA transfers to the first
contiguous RAM region (known as MEM1).
For example, up to 3 bytes of the last word of a DMA transfer of a
non-32 bit aligned length to MEM1 may be lost.
Such restrictions do not apply when using the second contiguous RAM
region (known as MEM2).

Add a set of DMA mapping operations which said devices can use to make
sure that DMA transfers are always performed to/from memory buffers
within MEM2.

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
---
 arch/powerpc/boot/wii.c                      |   34 ++++
 arch/powerpc/include/asm/wii.h               |   25 +++
 arch/powerpc/platforms/embedded6xx/Kconfig   |    1 +
 arch/powerpc/platforms/embedded6xx/Makefile  |    2 +-
 arch/powerpc/platforms/embedded6xx/wii-dma.c |  255 ++++++++++++++++++++++++++
 5 files changed, 316 insertions(+), 1 deletions(-)
 create mode 100644 arch/powerpc/include/asm/wii.h
 create mode 100755 arch/powerpc/platforms/embedded6xx/wii-dma.c

diff --git a/arch/powerpc/boot/wii.c b/arch/powerpc/boot/wii.c
index 2ebaec0..388e33d 100644
--- a/arch/powerpc/boot/wii.c
+++ b/arch/powerpc/boot/wii.c
@@ -30,6 +30,9 @@ BSS_STACK(8192);
 #define MEM2_TOP		(0x10000000 + 64*1024*1024)
 #define FIRMWARE_DEFAULT_SIZE	(12*1024*1024)
 
+#define MEM2_DMA_BASE_PROP	"linux,wii-mem2-dma-base"
+#define MEM2_DMA_SIZE_PROP	"linux,wii-mem2-dma-size"
+#define MEM2_DMA_DEFAULT_SIZE	(512*1024)
 
 struct mipc_infohdr {
 	char magic[3];
@@ -101,6 +104,30 @@ out:
 
 }
 
+static void mem2_fixups(u32 *top, u32 *reg)
+{
+	void *chosen;
+	u32 dma_base, dma_size;
+	int len;
+
+	chosen = finddevice("/chosen");
+	if (!chosen)
+		fatal("Can't find chosen node\n");
+
+	len = getprop(chosen, MEM2_DMA_SIZE_PROP, &dma_size, sizeof(dma_size));
+	if (len != sizeof(dma_size))
+		dma_size = MEM2_DMA_DEFAULT_SIZE;
+	if (dma_size > reg[3])
+		dma_size = reg[3];
+	setprop_val(chosen, MEM2_DMA_SIZE_PROP, dma_size);
+
+	*top -= dma_size;
+	dma_base = *top;
+	setprop_val(chosen, MEM2_DMA_BASE_PROP, dma_base);
+
+	printf("mem2_dma: %08X@%08X\n", dma_size, dma_base);
+}
+
 static void platform_fixups(void)
 {
 	void *mem;
@@ -127,9 +154,16 @@ static void platform_fixups(void)
 		mem2_boundary = MEM2_TOP - FIRMWARE_DEFAULT_SIZE;
 	}
 
+	mem2_fixups(&mem2_boundary, reg);
+
 	if (mem2_boundary > reg[2] && mem2_boundary < reg[2] + reg[3]) {
 		reg[3] = mem2_boundary - reg[2];
 		printf("top of MEM2 @ %08X\n", reg[2] + reg[3]);
+		/*
+		 * Find again the memory node as it may have changed its
+		 * position after adding some non-existing properties.
+		 */
+		mem = finddevice("/memory");
 		setprop(mem, "reg", reg, sizeof(reg));
 	}
 
diff --git a/arch/powerpc/include/asm/wii.h b/arch/powerpc/include/asm/wii.h
new file mode 100644
index 0000000..bb83c32
--- /dev/null
+++ b/arch/powerpc/include/asm/wii.h
@@ -0,0 +1,25 @@
+/*
+ * arch/powerpc/include/asm/wii.h
+ *
+ * Nintendo Wii board-specific definitions
+ * Copyright (C) 2010 The GameCube Linux Team
+ * Copyright (C) 2010 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#ifndef __ASM_POWERPC_WII_H
+#define __ASM_POWERPC_WII_H
+
+/*
+ * DMA operations for the Nintendo Wii.
+ */
+extern struct dma_map_ops wii_mem2_dma_ops;
+
+extern int wii_set_mem2_dma_constraints(struct device *dev);
+extern void wii_clear_mem2_dma_constraints(struct device *dev);
+
+#endif /* __ASM_POWERPC_WII_H */
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index fe77ab2..f4fff0a 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -120,6 +120,7 @@ config WII
 	depends on EMBEDDED6xx
 	select GAMECUBE_COMMON
 	select HAVE_GENERIC_DMA_COHERENT
+	select SWIOTLB
 	help
 	  Select WII if configuring for the Nintendo Wii.
 	  More information at: <http://gc-linux.sourceforge.net/>
diff --git a/arch/powerpc/platforms/embedded6xx/Makefile b/arch/powerpc/platforms/embedded6xx/Makefile
index 66c23e4..4d4c776 100644
--- a/arch/powerpc/platforms/embedded6xx/Makefile
+++ b/arch/powerpc/platforms/embedded6xx/Makefile
@@ -10,4 +10,4 @@ obj-$(CONFIG_PPC_C2K)		+= c2k.o
 obj-$(CONFIG_USBGECKO_UDBG)	+= usbgecko_udbg.o
 obj-$(CONFIG_GAMECUBE_COMMON)	+= flipper-pic.o
 obj-$(CONFIG_GAMECUBE)		+= gamecube.o
-obj-$(CONFIG_WII)		+= wii.o hlwd-pic.o
+obj-$(CONFIG_WII)		+= wii.o hlwd-pic.o wii-dma.o
diff --git a/arch/powerpc/platforms/embedded6xx/wii-dma.c b/arch/powerpc/platforms/embedded6xx/wii-dma.c
new file mode 100755
index 0000000..ff2eb67
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/wii-dma.c
@@ -0,0 +1,255 @@
+/*
+ * arch/powerpc/platforms/embedded6xx/wii-dma.c
+ *
+ * DMA functions for the Nintendo Wii video game console.
+ * Copyright (C) 2010 The GameCube Linux Team
+ * Copyright (C) 2010 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/kernel.h>
+#include <linux/bootmem.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/of.h>
+#include <linux/lmb.h>
+#include <asm/wii.h>
+
+#include "mm/mmu_decl.h"
+
+/* same as in arch/powerpc/boot/wii.c */
+#define MEM2_DMA_BASE_PROP	"linux,wii-mem2-dma-base"
+#define MEM2_DMA_SIZE_PROP	"linux,wii-mem2-dma-size"
+
+/*
+ * The Nintendo Wii video game console is a NOT_COHERENT_CACHE
+ * platform that is unable to safely perform non-32 bit uncached writes
+ * to RAM because the byte enables are not connected to the bus.
+ * Thus, in this platform, "coherent" DMA buffers cannot be directly used
+ * by the kernel code unless it guarantees that all write accesses
+ * to said buffers are done in 32 bit chunks.
+ *
+ * In addition, some of the devices in the "Hollywood" chipset have a
+ * similar restriction regarding DMA transfers: those with non-32bit
+ * aligned lengths only work when performed to/from the second contiguous
+ * region of memory (known as MEM2).
+ *
+ * To solve these issues a specific set of dma mapping operations is made
+ * available for devices requiring it. When enabled, the kernel will make
+ * sure that DMA buffers sitting in MEM1 get bounced to/from DMA buffers
+ * allocated from MEM2.
+ *
+ * Bouncing is performed with the help of the swiotlb support.
+ */
+
+/*
+ * Allocate the SWIOTLB from MEM2.
+ */
+void * __init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
+{
+	return __alloc_bootmem_low(size, PAGE_SIZE,
+				   wii_hole_start + wii_hole_size);
+}
+
+/*
+ * The mem2_dma "device".
+ *
+ * This device "owns" a pool of coherent MEM2 memory that can be shared among
+ * several devices requiring MEM2 DMA buffers, instead of dedicating specific
+ * pools for each device.
+ *
+ * A device can use the shared coherent MEM2 memory pool by calling
+ * wii_set_mem2_dma_constraints().
+ *
+ */
+
+struct mem2_dma {
+	struct platform_device *pdev;
+
+	dma_addr_t dma_base;
+	void *base;
+	size_t size;
+};
+
+static struct mem2_dma mem2_dma_instance;
+
+static inline struct mem2_dma *mem2_dma_get_instance(void)
+{
+	return &mem2_dma_instance;
+}
+
+static int __init mem2_dma_init(dma_addr_t dma_base, size_t size)
+{
+	struct mem2_dma *mem2_dma = mem2_dma_get_instance();
+	const int flags = DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE;
+	struct device *dev;
+	int error = 0;
+
+	mem2_dma->pdev = platform_device_register_simple("mem2_dma",
+							 0, NULL, 0);
+	if (IS_ERR(mem2_dma->pdev)) {
+		error = PTR_ERR(mem2_dma->pdev);
+		pr_err("error %d registering platform device\n", error);
+		goto err_pdev_register;
+	}
+	dev = &mem2_dma->pdev->dev;
+
+	if (!dma_declare_coherent_memory(dev, dma_base, dma_base,
+					 size, flags)) {
+		dev_err(dev, "error declaring coherent memory %zu@%Lx\n",
+			size, (unsigned long long)dma_base);
+		error = -EBUSY;
+		goto err_declare_coherent;
+	}
+	mem2_dma->dma_base = dma_base;
+	mem2_dma->size = size;
+	dev_info(dev, "using %zu KiB at 0x%Lx\n", size / 1024,
+		 (unsigned long long)dma_base);
+	goto out;
+
+err_declare_coherent:
+	platform_device_unregister(mem2_dma->pdev);
+err_pdev_register:
+	mem2_dma->pdev = NULL;
+out:
+	return error;
+}
+
+static int __init mem2_dma_setup(void)
+{
+	const dma_addr_t *dma_base;
+	const size_t *dma_size;
+	int error = -ENODEV;
+
+	dma_base = of_get_property(of_chosen, MEM2_DMA_BASE_PROP, NULL);
+	if (!dma_base) {
+		pr_err("can't find %s property\n", MEM2_DMA_BASE_PROP);
+		goto out;
+	}
+
+	dma_size = of_get_property(of_chosen, MEM2_DMA_SIZE_PROP, NULL);
+	if (!dma_size) {
+		pr_err("can't find %s property\n", MEM2_DMA_SIZE_PROP);
+		goto out;
+	}
+
+	error = mem2_dma_init(*dma_base, *dma_size);
+	if (error)
+		pr_err("error %d during setup\n", error);
+out:
+	return error;
+}
+arch_initcall(mem2_dma_setup);
+
+/**
+ * wii_mem2_dma_dev() - returns the device "owning" the shared MEM2 DMA region
+ *
+ * Use this function to retrieve the device for which the shared pool of
+ * coherent MEM2 memory has been registered.
+ */
+static struct device *wii_mem2_dma_dev(void)
+{
+	struct mem2_dma *mem2_dma = mem2_dma_get_instance();
+	BUG_ON(!mem2_dma->pdev);
+	return &mem2_dma->pdev->dev;
+}
+
+/**
+ * wii_set_mem2_dma_constraints() - forces device to use MEM2 DMA buffers only
+ * @dev:	device for which DMA constraints are defined
+ *
+ * Instructs device @dev to always use MEM2 DMA buffers for DMA transfers.
+ */
+int wii_set_mem2_dma_constraints(struct device *dev)
+{
+	struct dev_archdata *sd;
+
+	sd = &dev->archdata;
+	sd->max_direct_dma_addr = 0;
+	sd->min_direct_dma_addr = wii_hole_start + wii_hole_size;
+
+	set_dma_ops(dev, &wii_mem2_dma_ops);
+	return 0;
+}
+EXPORT_SYMBOL(wii_set_mem2_dma_constraints);
+
+/**
+ * wii_clear_mem2_dma_constraints() - clears device MEM2 DMA constraints
+ * @dev:	device for which DMA constraints are cleared
+ *
+ * Instructs device @dev to stop using MEM2 DMA buffers for DMA transfers.
+ * Must be called to undo wii_set_mem2_dma_constraints().
+ */
+void wii_clear_mem2_dma_constraints(struct device *dev)
+{
+	struct dev_archdata *sd;
+
+	sd = &dev->archdata;
+	sd->max_direct_dma_addr = 0;
+	sd->min_direct_dma_addr = 0;
+
+	set_dma_ops(dev, &dma_direct_ops);
+}
+EXPORT_SYMBOL(wii_clear_mem2_dma_constraints);
+
+/*
+ * Determines if a given DMA region specified by @dma_handle
+ * requires bouncing.
+ *
+ * Bouncing is required if the DMA region falls within MEM1.
+ */
+static int mem2_needs_dmabounce(dma_addr_t dma_handle)
+{
+	return dma_handle < wii_hole_start;
+}
+
+/*
+ * Use the dma_direct_ops hooks for allocating and freeing coherent memory.
+ */
+
+static void *mem2_alloc_coherent(struct device *dev, size_t size,
+				 dma_addr_t *dma_handle, gfp_t gfp)
+{
+	void *vaddr;
+
+	vaddr = dma_direct_ops.alloc_coherent(wii_mem2_dma_dev(), size,
+					      dma_handle, gfp);
+	if (vaddr && mem2_needs_dmabounce(*dma_handle)) {
+		dma_direct_ops.free_coherent(wii_mem2_dma_dev(), size, vaddr,
+					     *dma_handle);
+		dev_err(wii_mem2_dma_dev(), "failed to allocate MEM2 coherent"
+			" memory\n");
+		vaddr = NULL;
+	}
+	return vaddr;
+}
+
+static void mem2_free_coherent(struct device *dev, size_t size,
+			       void *vaddr, dma_addr_t dma_handle)
+{
+	dma_direct_ops.free_coherent(wii_mem2_dma_dev(), size, vaddr,
+				     dma_handle);
+}
+
+/*
+ * Set of DMA operations for devices requiring MEM2 DMA buffers.
+ */
+struct dma_map_ops wii_mem2_dma_ops = {
+	.alloc_coherent = mem2_alloc_coherent,
+	.free_coherent = mem2_free_coherent,
+	.map_sg = swiotlb_map_sg_attrs,
+	.unmap_sg = swiotlb_unmap_sg_attrs,
+	.dma_supported = swiotlb_dma_supported,
+	.map_page = swiotlb_map_page,
+	.unmap_page = swiotlb_unmap_page,
+	.sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu,
+	.sync_single_range_for_device = swiotlb_sync_single_range_for_device,
+	.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
+	.sync_sg_for_device = swiotlb_sync_sg_for_cpu,
+	.mapping_error = swiotlb_dma_mapping_error,
+};
-- 
1.6.3.3

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

* [RFC PATCH v3 10/11] wii: enable swiotlb
  2010-03-07 12:11 [RFC PATCH v3 00/11] wii: add usb 2.0 support Albert Herranz
                   ` (8 preceding siblings ...)
  2010-03-07 12:11 ` [RFC PATCH v3 09/11] wii: add mem2 dma mapping ops Albert Herranz
@ 2010-03-07 12:11 ` Albert Herranz
  2010-03-07 12:11 ` [RFC PATCH v3 11/11] wii: hollywood ehci controller support Albert Herranz
  10 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz

Enable the use of a software IO TLB on the Nintendo Wii video game console.

This is used by the platform DMA support code to overcome the limitations
found in some of the devices within the "Hollywood" chipset.

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
---
 arch/powerpc/platforms/embedded6xx/wii.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c
index 57e5b60..6ad5c0a 100644
--- a/arch/powerpc/platforms/embedded6xx/wii.c
+++ b/arch/powerpc/platforms/embedded6xx/wii.c
@@ -164,6 +164,8 @@ static void __init wii_setup_arch(void)
 		clrbits32(hw_gpio + HW_GPIO_OUT(0),
 			  HW_GPIO_SLOT_LED | HW_GPIO_SENSOR_BAR);
 	}
+	swiotlb_set_default_size(1<<20); /* 1 MB */
+	ppc_swiotlb_enable = 1;
 }
 
 static void wii_restart(char *cmd)
-- 
1.6.3.3

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

* [RFC PATCH v3 11/11] wii: hollywood ehci controller support
  2010-03-07 12:11 [RFC PATCH v3 00/11] wii: add usb 2.0 support Albert Herranz
                   ` (9 preceding siblings ...)
  2010-03-07 12:11 ` [RFC PATCH v3 10/11] wii: enable swiotlb Albert Herranz
@ 2010-03-07 12:11 ` Albert Herranz
  10 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-07 12:11 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev; +Cc: Albert Herranz

Add support for the USB Enhanced Host Controller Interface included
in the "Hollywood" chipset of the Nintendo Wii video game console.

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
---
 arch/powerpc/platforms/embedded6xx/Kconfig |    1 +
 drivers/usb/host/Kconfig                   |    8 +
 drivers/usb/host/ehci-hcd.c                |    5 +
 drivers/usb/host/ehci-hlwd.c               |  233 ++++++++++++++++++++++++++++
 drivers/usb/host/ehci.h                    |   23 +++
 5 files changed, 270 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/host/ehci-hlwd.c

diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index f4fff0a..63bc708 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -121,6 +121,7 @@ config WII
 	select GAMECUBE_COMMON
 	select HAVE_GENERIC_DMA_COHERENT
 	select SWIOTLB
+	select USB_ARCH_HAS_EHCI
 	help
 	  Select WII if configuring for the Nintendo Wii.
 	  More information at: <http://gc-linux.sourceforge.net/>
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 2678a16..342954f 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -131,6 +131,14 @@ config USB_EHCI_HCD_PPC_OF
 	  Enables support for the USB controller present on the PowerPC
 	  OpenFirmware platform bus.
 
+config USB_EHCI_HCD_HLWD
+	bool "Nintendo Wii (Hollywood) EHCI USB controller support"
+	depends on USB_EHCI_HCD && WII
+	default y
+	---help---
+	  Say Y here to support the EHCI USB controller found in the
+	  Hollywood chipset of the Nintendo Wii video game console.
+
 config USB_W90X900_EHCI
 	bool "W90X900(W90P910) EHCI support"
 	depends on USB_EHCI_HCD && ARCH_W90X900
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 1ec3857..395c6a1 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1133,6 +1133,11 @@ MODULE_LICENSE ("GPL");
 #define OF_PLATFORM_DRIVER	ehci_hcd_ppc_of_driver
 #endif
 
+#ifdef CONFIG_USB_EHCI_HCD_HLWD
+#include "ehci-hlwd.c"
+#define OF_PLATFORM_DRIVER	ehci_hcd_hlwd_driver
+#endif
+
 #ifdef CONFIG_XPS_USB_HCD_XILINX
 #include "ehci-xilinx-of.c"
 #define OF_PLATFORM_DRIVER	ehci_hcd_xilinx_of_driver
diff --git a/drivers/usb/host/ehci-hlwd.c b/drivers/usb/host/ehci-hlwd.c
new file mode 100644
index 0000000..129e96b
--- /dev/null
+++ b/drivers/usb/host/ehci-hlwd.c
@@ -0,0 +1,233 @@
+/*
+ * drivers/usb/host/ehci-hlwd.c
+ *
+ * Nintendo Wii (Hollywood) USB Enhanced Host Controller Interface.
+ * Copyright (C) 2009-2010 The GameCube Linux Team
+ * Copyright (C) 2009,2010 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * Based on ehci-ppc-of.c
+ *
+ * EHCI HCD (Host Controller Driver) for USB.
+ *
+ * Bus Glue for PPC On-Chip EHCI driver on the of_platform bus
+ * Tested on AMCC PPC 440EPx
+ *
+ * Valentine Barshak <vbarshak@ru.mvista.com>
+ *
+ * Based on "ehci-ppc-soc.c" by Stefan Roese <sr@denx.de>
+ * and "ohci-ppc-of.c" by Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <linux/signal.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <asm/wii.h>
+
+#define DRV_MODULE_NAME "ehci-hlwd"
+#define DRV_DESCRIPTION "Nintendo Wii EHCI Host Controller"
+#define DRV_AUTHOR      "Albert Herranz"
+
+/*
+ * Non-standard registers.
+ */
+#define HLWD_EHCI_CTL		0x00cc	/* Controller Control */
+#define HLWD_EHCI_CTL_INTE	(1<<15)	/* Notify EHCI interrupts */
+
+/* called during probe() after chip reset completes */
+static int ehci_hlwd_reset(struct usb_hcd *hcd)
+{
+	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+	int error;
+
+	dbg_hcs_params(ehci, "reset");
+	dbg_hcc_params(ehci, "reset");
+
+	error = ehci_halt(ehci);
+	if (error)
+		goto out;
+
+	error = ehci_init(hcd);
+	if (error)
+		goto out;
+
+	/* enable notification of EHCI interrupts */
+	setbits32(hcd->regs + HLWD_EHCI_CTL, HLWD_EHCI_CTL_INTE);
+
+	ehci->sbrn = 0x20;
+	error = ehci_reset(ehci);
+	ehci_port_power(ehci, 0);
+out:
+	return error;
+}
+
+static const struct hc_driver ehci_hlwd_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "Nintendo Wii EHCI Host Controller",
+	.hcd_priv_size		= sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq			= ehci_irq,
+	.flags			= HCD_USB2 | HCD_NO_COHERENT_MEM,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset			= ehci_hlwd_reset,
+	.start			= ehci_run,
+	.stop			= ehci_stop,
+	.shutdown		= ehci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.endpoint_disable	= ehci_endpoint_disable,
+	.endpoint_reset		= ehci_endpoint_reset,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number	= ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= ehci_hub_control,
+#ifdef	CONFIG_PM
+	.bus_suspend		= ehci_bus_suspend,
+	.bus_resume		= ehci_bus_resume,
+#endif
+	.relinquish_port	= ehci_relinquish_port,
+	.port_handed_over	= ehci_port_handed_over,
+
+	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+};
+
+static int __devinit
+ehci_hcd_hlwd_probe(struct of_device *op, const struct of_device_id *match)
+{
+	struct device_node *dn = op->node;
+	struct usb_hcd *hcd;
+	struct ehci_hcd	*ehci = NULL;
+	struct resource res;
+	int irq;
+	int error = -ENODEV;
+
+	if (usb_disabled())
+		goto out;
+
+	dev_dbg(&op->dev, "initializing " DRV_MODULE_NAME " USB Controller\n");
+
+	error = of_address_to_resource(dn, 0, &res);
+	if (error)
+		goto out;
+
+	hcd = usb_create_hcd(&ehci_hlwd_hc_driver, &op->dev, DRV_MODULE_NAME);
+	if (!hcd) {
+		error = -ENOMEM;
+		goto out;
+	}
+
+	hcd->rsrc_start = res.start;
+	hcd->rsrc_len = resource_size(&res);
+
+	irq = irq_of_parse_and_map(dn, 0);
+	if (irq == NO_IRQ) {
+		printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n");
+		error = -EBUSY;
+		goto err_irq;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		printk(KERN_ERR __FILE__ ": ioremap failed\n");
+		error = -EBUSY;
+		goto err_ioremap;
+	}
+
+	/* this device requires MEM2 DMA buffers */
+	error = wii_set_mem2_dma_constraints(&op->dev);
+	if (error)
+		goto err_mem2_constraints;
+
+	ehci = hcd_to_ehci(hcd);
+	ehci->caps = hcd->regs;
+	ehci->regs = hcd->regs +
+			HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+
+	/* cache this readonly data; minimize chip reads */
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+	error = usb_add_hcd(hcd, irq, 0);
+	if (error == 0)
+		return 0;
+
+err_mem2_constraints:
+	iounmap(hcd->regs);
+err_ioremap:
+	irq_dispose_mapping(irq);
+err_irq:
+	usb_put_hcd(hcd);
+out:
+	return error;
+}
+
+
+static int ehci_hcd_hlwd_remove(struct of_device *op)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+
+	dev_set_drvdata(&op->dev, NULL);
+
+	dev_dbg(&op->dev, "stopping " DRV_MODULE_NAME " USB Controller\n");
+
+	usb_remove_hcd(hcd);
+	wii_clear_mem2_dma_constraints(&op->dev);
+	iounmap(hcd->regs);
+	irq_dispose_mapping(hcd->irq);
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+
+static int ehci_hcd_hlwd_shutdown(struct of_device *op)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+
+	if (hcd->driver->shutdown)
+		hcd->driver->shutdown(hcd);
+
+	return 0;
+}
+
+
+static struct of_device_id ehci_hcd_hlwd_match[] = {
+	{ .compatible = "nintendo,hollywood-usb-ehci", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ehci_hcd_hlwd_match);
+
+static struct of_platform_driver ehci_hcd_hlwd_driver = {
+	.name		= DRV_MODULE_NAME,
+	.match_table	= ehci_hcd_hlwd_match,
+	.probe		= ehci_hcd_hlwd_probe,
+	.remove		= ehci_hcd_hlwd_remove,
+	.shutdown	= ehci_hcd_hlwd_shutdown,
+	.driver		= {
+		.name	= DRV_MODULE_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 2d85e21..8fb519b 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -599,6 +599,27 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
 #define ehci_big_endian_mmio(e)		0
 #endif
 
+#ifdef CONFIG_USB_EHCI_HCD_HLWD
+
+/*
+ * The Nintendo Wii video game console has no PCI hardware.
+ * The USB controllers are part of the "Hollywood" chipset and are
+ * accessed via the platform internal I/O accessors.
+ */
+static inline unsigned int ehci_readl(const struct ehci_hcd *ehci,
+				      __u32 __iomem *regs)
+{
+	return in_be32(regs);
+}
+
+static inline void ehci_writel(const struct ehci_hcd *ehci,
+			       const unsigned int val, __u32 __iomem *regs)
+{
+	out_be32(regs, val);
+}
+
+#else
+
 /*
  * Big-endian read/write functions are arch-specific.
  * Other arches can be added if/when they're needed.
@@ -632,6 +653,8 @@ static inline void ehci_writel(const struct ehci_hcd *ehci,
 #endif
 }
 
+#endif /* CONFIG_USB_EHCI_HCD_HLWD */
+
 /*
  * On certain ppc-44x SoC there is a HW issue, that could only worked around with
  * explicit suspend/operate of OHCI. This function hereby makes sense only on that arch.
-- 
1.6.3.3

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

* Re: [LKML] [RFC PATCH v3 04/11] swiotlb: support NOT_COHERENT_CACHE PowerPC platforms
  2010-03-07 12:11   ` Albert Herranz
  (?)
@ 2010-03-08 16:55     ` Konrad Rzeszutek Wilk
  -1 siblings, 0 replies; 30+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-03-08 16:55 UTC (permalink / raw)
  To: Albert Herranz; +Cc: linux-usb, linuxppc-dev, linux-kernel, x86, linux-ia64

On Sun, Mar 07, 2010 at 01:11:45PM +0100, Albert Herranz wrote:
> The current SWIOTLB code does not support NOT_COHERENT_CACHE platforms.
> This patch adds support for NOT_COHERENT_CACHE platforms to SWIOTLB by
> adding two platform specific functions swiotlb_dma_sync_page() and
> swiotlb_dma_sync() which can be used to explicitly manage cache coherency.

Hey Albert,

I've been doing some posting in this area to split the physical / bus
address translation so that multiple platforms can utilize it. I was
wondering if it makes sense to utilize some of those concepts (ie, extend it
for DMA coherency) for your code:

https://lists.linux-foundation.org/pipermail/iommu/2010-February/002066.html

And here is the git tree that goes on top of those patches:
git://git.kernel.org/pub/scm/linux/kernel/git/konrad/swiotlb-2.6.git xen-swiotlb-0.5


> 
> On PowerPC these functions are mapped to their corresponding
> __dma_sync_page() and __dma_sync() functions.
> On other architectures using SWIOTLB these functions are optimized out.
> 
> This will be used later to support SWIOTLB on the Nintendo Wii video game
> console.
> 
> Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
> CC: linuxppc-dev@lists.ozlabs.org
> CC: linux-kernel@vger.kernel.org
> CC: x86@kernel.org
> CC: linux-ia64@vger.kernel.org
> ---
>  arch/ia64/include/asm/swiotlb.h    |   10 ++++++++++
>  arch/powerpc/include/asm/swiotlb.h |    3 +++
>  arch/x86/include/asm/swiotlb.h     |   10 ++++++++++
>  lib/swiotlb.c                      |   30 ++++++++++++++++++++++++------
>  4 files changed, 47 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/ia64/include/asm/swiotlb.h b/arch/ia64/include/asm/swiotlb.h
> index f0acde6..6722090 100644
> --- a/arch/ia64/include/asm/swiotlb.h
> +++ b/arch/ia64/include/asm/swiotlb.h
> @@ -14,4 +14,14 @@ static inline void pci_swiotlb_init(void)
>  }
>  #endif
>  
> +static inline void swiotlb_dma_sync_page(struct page *page,
> +					 unsigned long offset,
> +					 size_t size, int direction)
> +{
> +}
> +
> +static inline void swiotlb_dma_sync(void *vaddr, size_t size, int direction)
> +{
> +}
> +
>  #endif /* ASM_IA64__SWIOTLB_H */
> diff --git a/arch/powerpc/include/asm/swiotlb.h b/arch/powerpc/include/asm/swiotlb.h
> index 8979d4c..603b343 100644
> --- a/arch/powerpc/include/asm/swiotlb.h
> +++ b/arch/powerpc/include/asm/swiotlb.h
> @@ -22,4 +22,7 @@ int __init swiotlb_setup_bus_notifier(void);
>  
>  extern void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev);
>  
> +#define swiotlb_dma_sync_page __dma_sync_page
> +#define swiotlb_dma_sync __dma_sync
> +
>  #endif /* __ASM_SWIOTLB_H */
> diff --git a/arch/x86/include/asm/swiotlb.h b/arch/x86/include/asm/swiotlb.h
> index 8085277..e5f6d9c 100644
> --- a/arch/x86/include/asm/swiotlb.h
> +++ b/arch/x86/include/asm/swiotlb.h
> @@ -20,4 +20,14 @@ static inline void pci_swiotlb_init(void)
>  
>  static inline void dma_mark_clean(void *addr, size_t size) {}
>  
> +static inline void swiotlb_dma_sync_page(struct page *page,
> +					 unsigned long offset,
> +					 size_t size, int direction)
> +{
> +}
> +
> +static inline void swiotlb_dma_sync(void *vaddr, size_t size, int direction)
> +{
> +}
> +
>  #endif /* _ASM_X86_SWIOTLB_H */
> diff --git a/lib/swiotlb.c b/lib/swiotlb.c
> index 94db5df..8f2dad9 100644
> --- a/lib/swiotlb.c
> +++ b/lib/swiotlb.c
> @@ -346,10 +346,13 @@ static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
>  			local_irq_save(flags);
>  			buffer = kmap_atomic(pfn_to_page(pfn),
>  					     KM_BOUNCE_READ);
> -			if (dir == DMA_TO_DEVICE)
> +			if (dir == DMA_TO_DEVICE) {
>  				memcpy(dma_addr, buffer + offset, sz);
> -			else
> +				swiotlb_dma_sync(dma_addr, sz, dir);
> +			} else {
> +				swiotlb_dma_sync(dma_addr, sz, dir);
>  				memcpy(buffer + offset, dma_addr, sz);
> +			}
>  			kunmap_atomic(buffer, KM_BOUNCE_READ);
>  			local_irq_restore(flags);
>  
> @@ -359,10 +362,14 @@ static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
>  			offset = 0;
>  		}
>  	} else {
> -		if (dir == DMA_TO_DEVICE)
> +		if (dir == DMA_TO_DEVICE) {
>  			memcpy(dma_addr, phys_to_virt(phys), size);
> -		else
> +			swiotlb_dma_sync(dma_addr, size, dir);
> +
> +		} else {
> +			swiotlb_dma_sync(dma_addr, size, dir);
>  			memcpy(phys_to_virt(phys), dma_addr, size);
> +		}
>  	}
>  }
>  
> @@ -542,6 +549,8 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size,
>  	}
>  }
>  
> +#ifndef CONFIG_NOT_COHERENT_CACHE
> +
>  void *
>  swiotlb_alloc_coherent(struct device *hwdev, size_t size,
>  		       dma_addr_t *dma_handle, gfp_t flags)
> @@ -606,6 +615,8 @@ swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
>  }
>  EXPORT_SYMBOL(swiotlb_free_coherent);
>  
> +#endif /* !CONFIG_NOT_COHERENT_CACHE */
> +
>  static void
>  swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
>  {
> @@ -652,8 +663,10 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
>  	 * we can safely return the device addr and not worry about bounce
>  	 * buffering it.
>  	 */
> -	if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
> +	if (dma_capable(dev, dev_addr, size) && !swiotlb_force) {
> +		swiotlb_dma_sync_page(page, offset, size, dir);
>  		return dev_addr;
> +	}
>  
>  	/*
>  	 * Oh well, have to allocate and map a bounce buffer.
> @@ -739,6 +752,8 @@ swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
>  		return;
>  	}
>  
> +	swiotlb_dma_sync(phys_to_virt(paddr), size, dir);
> +
>  	if (dir != DMA_FROM_DEVICE)
>  		return;
>  
> @@ -835,8 +850,11 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
>  				return 0;
>  			}
>  			sg->dma_address = swiotlb_virt_to_bus(hwdev, map);
> -		} else
> +		} else {
> +			swiotlb_dma_sync_page(sg_page(sg), sg->offset,
> +					      sg->length, dir);
>  			sg->dma_address = dev_addr;
> +		}
>  		sg->dma_length = sg->length;
>  	}
>  	return nelems;
> -- 
> 1.6.3.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [LKML] [RFC PATCH v3 04/11] swiotlb: support NOT_COHERENT_CACHE PowerPC platforms
@ 2010-03-08 16:55     ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 30+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-03-08 16:55 UTC (permalink / raw)
  To: Albert Herranz; +Cc: x86, linux-ia64, linux-usb, linuxppc-dev, linux-kernel

On Sun, Mar 07, 2010 at 01:11:45PM +0100, Albert Herranz wrote:
> The current SWIOTLB code does not support NOT_COHERENT_CACHE platforms.
> This patch adds support for NOT_COHERENT_CACHE platforms to SWIOTLB by
> adding two platform specific functions swiotlb_dma_sync_page() and
> swiotlb_dma_sync() which can be used to explicitly manage cache coherency.

Hey Albert,

I've been doing some posting in this area to split the physical / bus
address translation so that multiple platforms can utilize it. I was
wondering if it makes sense to utilize some of those concepts (ie, extend it
for DMA coherency) for your code:

https://lists.linux-foundation.org/pipermail/iommu/2010-February/002066.html

And here is the git tree that goes on top of those patches:
git://git.kernel.org/pub/scm/linux/kernel/git/konrad/swiotlb-2.6.git xen-swiotlb-0.5


> 
> On PowerPC these functions are mapped to their corresponding
> __dma_sync_page() and __dma_sync() functions.
> On other architectures using SWIOTLB these functions are optimized out.
> 
> This will be used later to support SWIOTLB on the Nintendo Wii video game
> console.
> 
> Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
> CC: linuxppc-dev@lists.ozlabs.org
> CC: linux-kernel@vger.kernel.org
> CC: x86@kernel.org
> CC: linux-ia64@vger.kernel.org
> ---
>  arch/ia64/include/asm/swiotlb.h    |   10 ++++++++++
>  arch/powerpc/include/asm/swiotlb.h |    3 +++
>  arch/x86/include/asm/swiotlb.h     |   10 ++++++++++
>  lib/swiotlb.c                      |   30 ++++++++++++++++++++++++------
>  4 files changed, 47 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/ia64/include/asm/swiotlb.h b/arch/ia64/include/asm/swiotlb.h
> index f0acde6..6722090 100644
> --- a/arch/ia64/include/asm/swiotlb.h
> +++ b/arch/ia64/include/asm/swiotlb.h
> @@ -14,4 +14,14 @@ static inline void pci_swiotlb_init(void)
>  }
>  #endif
>  
> +static inline void swiotlb_dma_sync_page(struct page *page,
> +					 unsigned long offset,
> +					 size_t size, int direction)
> +{
> +}
> +
> +static inline void swiotlb_dma_sync(void *vaddr, size_t size, int direction)
> +{
> +}
> +
>  #endif /* ASM_IA64__SWIOTLB_H */
> diff --git a/arch/powerpc/include/asm/swiotlb.h b/arch/powerpc/include/asm/swiotlb.h
> index 8979d4c..603b343 100644
> --- a/arch/powerpc/include/asm/swiotlb.h
> +++ b/arch/powerpc/include/asm/swiotlb.h
> @@ -22,4 +22,7 @@ int __init swiotlb_setup_bus_notifier(void);
>  
>  extern void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev);
>  
> +#define swiotlb_dma_sync_page __dma_sync_page
> +#define swiotlb_dma_sync __dma_sync
> +
>  #endif /* __ASM_SWIOTLB_H */
> diff --git a/arch/x86/include/asm/swiotlb.h b/arch/x86/include/asm/swiotlb.h
> index 8085277..e5f6d9c 100644
> --- a/arch/x86/include/asm/swiotlb.h
> +++ b/arch/x86/include/asm/swiotlb.h
> @@ -20,4 +20,14 @@ static inline void pci_swiotlb_init(void)
>  
>  static inline void dma_mark_clean(void *addr, size_t size) {}
>  
> +static inline void swiotlb_dma_sync_page(struct page *page,
> +					 unsigned long offset,
> +					 size_t size, int direction)
> +{
> +}
> +
> +static inline void swiotlb_dma_sync(void *vaddr, size_t size, int direction)
> +{
> +}
> +
>  #endif /* _ASM_X86_SWIOTLB_H */
> diff --git a/lib/swiotlb.c b/lib/swiotlb.c
> index 94db5df..8f2dad9 100644
> --- a/lib/swiotlb.c
> +++ b/lib/swiotlb.c
> @@ -346,10 +346,13 @@ static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
>  			local_irq_save(flags);
>  			buffer = kmap_atomic(pfn_to_page(pfn),
>  					     KM_BOUNCE_READ);
> -			if (dir == DMA_TO_DEVICE)
> +			if (dir == DMA_TO_DEVICE) {
>  				memcpy(dma_addr, buffer + offset, sz);
> -			else
> +				swiotlb_dma_sync(dma_addr, sz, dir);
> +			} else {
> +				swiotlb_dma_sync(dma_addr, sz, dir);
>  				memcpy(buffer + offset, dma_addr, sz);
> +			}
>  			kunmap_atomic(buffer, KM_BOUNCE_READ);
>  			local_irq_restore(flags);
>  
> @@ -359,10 +362,14 @@ static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
>  			offset = 0;
>  		}
>  	} else {
> -		if (dir == DMA_TO_DEVICE)
> +		if (dir == DMA_TO_DEVICE) {
>  			memcpy(dma_addr, phys_to_virt(phys), size);
> -		else
> +			swiotlb_dma_sync(dma_addr, size, dir);
> +
> +		} else {
> +			swiotlb_dma_sync(dma_addr, size, dir);
>  			memcpy(phys_to_virt(phys), dma_addr, size);
> +		}
>  	}
>  }
>  
> @@ -542,6 +549,8 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size,
>  	}
>  }
>  
> +#ifndef CONFIG_NOT_COHERENT_CACHE
> +
>  void *
>  swiotlb_alloc_coherent(struct device *hwdev, size_t size,
>  		       dma_addr_t *dma_handle, gfp_t flags)
> @@ -606,6 +615,8 @@ swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
>  }
>  EXPORT_SYMBOL(swiotlb_free_coherent);
>  
> +#endif /* !CONFIG_NOT_COHERENT_CACHE */
> +
>  static void
>  swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
>  {
> @@ -652,8 +663,10 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
>  	 * we can safely return the device addr and not worry about bounce
>  	 * buffering it.
>  	 */
> -	if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
> +	if (dma_capable(dev, dev_addr, size) && !swiotlb_force) {
> +		swiotlb_dma_sync_page(page, offset, size, dir);
>  		return dev_addr;
> +	}
>  
>  	/*
>  	 * Oh well, have to allocate and map a bounce buffer.
> @@ -739,6 +752,8 @@ swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
>  		return;
>  	}
>  
> +	swiotlb_dma_sync(phys_to_virt(paddr), size, dir);
> +
>  	if (dir != DMA_FROM_DEVICE)
>  		return;
>  
> @@ -835,8 +850,11 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
>  				return 0;
>  			}
>  			sg->dma_address = swiotlb_virt_to_bus(hwdev, map);
> -		} else
> +		} else {
> +			swiotlb_dma_sync_page(sg_page(sg), sg->offset,
> +					      sg->length, dir);
>  			sg->dma_address = dev_addr;
> +		}
>  		sg->dma_length = sg->length;
>  	}
>  	return nelems;
> -- 
> 1.6.3.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [LKML] [RFC PATCH v3 04/11] swiotlb: support
@ 2010-03-08 16:55     ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 30+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-03-08 16:55 UTC (permalink / raw)
  To: Albert Herranz; +Cc: linux-usb, linuxppc-dev, linux-kernel, x86, linux-ia64

On Sun, Mar 07, 2010 at 01:11:45PM +0100, Albert Herranz wrote:
> The current SWIOTLB code does not support NOT_COHERENT_CACHE platforms.
> This patch adds support for NOT_COHERENT_CACHE platforms to SWIOTLB by
> adding two platform specific functions swiotlb_dma_sync_page() and
> swiotlb_dma_sync() which can be used to explicitly manage cache coherency.

Hey Albert,

I've been doing some posting in this area to split the physical / bus
address translation so that multiple platforms can utilize it. I was
wondering if it makes sense to utilize some of those concepts (ie, extend it
for DMA coherency) for your code:

https://lists.linux-foundation.org/pipermail/iommu/2010-February/002066.html

And here is the git tree that goes on top of those patches:
git://git.kernel.org/pub/scm/linux/kernel/git/konrad/swiotlb-2.6.git xen-swiotlb-0.5


> 
> On PowerPC these functions are mapped to their corresponding
> __dma_sync_page() and __dma_sync() functions.
> On other architectures using SWIOTLB these functions are optimized out.
> 
> This will be used later to support SWIOTLB on the Nintendo Wii video game
> console.
> 
> Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
> CC: linuxppc-dev@lists.ozlabs.org
> CC: linux-kernel@vger.kernel.org
> CC: x86@kernel.org
> CC: linux-ia64@vger.kernel.org
> ---
>  arch/ia64/include/asm/swiotlb.h    |   10 ++++++++++
>  arch/powerpc/include/asm/swiotlb.h |    3 +++
>  arch/x86/include/asm/swiotlb.h     |   10 ++++++++++
>  lib/swiotlb.c                      |   30 ++++++++++++++++++++++++------
>  4 files changed, 47 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/ia64/include/asm/swiotlb.h b/arch/ia64/include/asm/swiotlb.h
> index f0acde6..6722090 100644
> --- a/arch/ia64/include/asm/swiotlb.h
> +++ b/arch/ia64/include/asm/swiotlb.h
> @@ -14,4 +14,14 @@ static inline void pci_swiotlb_init(void)
>  }
>  #endif
>  
> +static inline void swiotlb_dma_sync_page(struct page *page,
> +					 unsigned long offset,
> +					 size_t size, int direction)
> +{
> +}
> +
> +static inline void swiotlb_dma_sync(void *vaddr, size_t size, int direction)
> +{
> +}
> +
>  #endif /* ASM_IA64__SWIOTLB_H */
> diff --git a/arch/powerpc/include/asm/swiotlb.h b/arch/powerpc/include/asm/swiotlb.h
> index 8979d4c..603b343 100644
> --- a/arch/powerpc/include/asm/swiotlb.h
> +++ b/arch/powerpc/include/asm/swiotlb.h
> @@ -22,4 +22,7 @@ int __init swiotlb_setup_bus_notifier(void);
>  
>  extern void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev);
>  
> +#define swiotlb_dma_sync_page __dma_sync_page
> +#define swiotlb_dma_sync __dma_sync
> +
>  #endif /* __ASM_SWIOTLB_H */
> diff --git a/arch/x86/include/asm/swiotlb.h b/arch/x86/include/asm/swiotlb.h
> index 8085277..e5f6d9c 100644
> --- a/arch/x86/include/asm/swiotlb.h
> +++ b/arch/x86/include/asm/swiotlb.h
> @@ -20,4 +20,14 @@ static inline void pci_swiotlb_init(void)
>  
>  static inline void dma_mark_clean(void *addr, size_t size) {}
>  
> +static inline void swiotlb_dma_sync_page(struct page *page,
> +					 unsigned long offset,
> +					 size_t size, int direction)
> +{
> +}
> +
> +static inline void swiotlb_dma_sync(void *vaddr, size_t size, int direction)
> +{
> +}
> +
>  #endif /* _ASM_X86_SWIOTLB_H */
> diff --git a/lib/swiotlb.c b/lib/swiotlb.c
> index 94db5df..8f2dad9 100644
> --- a/lib/swiotlb.c
> +++ b/lib/swiotlb.c
> @@ -346,10 +346,13 @@ static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
>  			local_irq_save(flags);
>  			buffer = kmap_atomic(pfn_to_page(pfn),
>  					     KM_BOUNCE_READ);
> -			if (dir = DMA_TO_DEVICE)
> +			if (dir = DMA_TO_DEVICE) {
>  				memcpy(dma_addr, buffer + offset, sz);
> -			else
> +				swiotlb_dma_sync(dma_addr, sz, dir);
> +			} else {
> +				swiotlb_dma_sync(dma_addr, sz, dir);
>  				memcpy(buffer + offset, dma_addr, sz);
> +			}
>  			kunmap_atomic(buffer, KM_BOUNCE_READ);
>  			local_irq_restore(flags);
>  
> @@ -359,10 +362,14 @@ static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
>  			offset = 0;
>  		}
>  	} else {
> -		if (dir = DMA_TO_DEVICE)
> +		if (dir = DMA_TO_DEVICE) {
>  			memcpy(dma_addr, phys_to_virt(phys), size);
> -		else
> +			swiotlb_dma_sync(dma_addr, size, dir);
> +
> +		} else {
> +			swiotlb_dma_sync(dma_addr, size, dir);
>  			memcpy(phys_to_virt(phys), dma_addr, size);
> +		}
>  	}
>  }
>  
> @@ -542,6 +549,8 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size,
>  	}
>  }
>  
> +#ifndef CONFIG_NOT_COHERENT_CACHE
> +
>  void *
>  swiotlb_alloc_coherent(struct device *hwdev, size_t size,
>  		       dma_addr_t *dma_handle, gfp_t flags)
> @@ -606,6 +615,8 @@ swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
>  }
>  EXPORT_SYMBOL(swiotlb_free_coherent);
>  
> +#endif /* !CONFIG_NOT_COHERENT_CACHE */
> +
>  static void
>  swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
>  {
> @@ -652,8 +663,10 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
>  	 * we can safely return the device addr and not worry about bounce
>  	 * buffering it.
>  	 */
> -	if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
> +	if (dma_capable(dev, dev_addr, size) && !swiotlb_force) {
> +		swiotlb_dma_sync_page(page, offset, size, dir);
>  		return dev_addr;
> +	}
>  
>  	/*
>  	 * Oh well, have to allocate and map a bounce buffer.
> @@ -739,6 +752,8 @@ swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
>  		return;
>  	}
>  
> +	swiotlb_dma_sync(phys_to_virt(paddr), size, dir);
> +
>  	if (dir != DMA_FROM_DEVICE)
>  		return;
>  
> @@ -835,8 +850,11 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
>  				return 0;
>  			}
>  			sg->dma_address = swiotlb_virt_to_bus(hwdev, map);
> -		} else
> +		} else {
> +			swiotlb_dma_sync_page(sg_page(sg), sg->offset,
> +					      sg->length, dir);
>  			sg->dma_address = dev_addr;
> +		}
>  		sg->dma_length = sg->length;
>  	}
>  	return nelems;
> -- 
> 1.6.3.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [LKML] [RFC PATCH v3 05/11] swiotlb: add swiotlb_set_default_size()
  2010-03-07 12:11   ` Albert Herranz
  (?)
@ 2010-03-08 16:59     ` Konrad Rzeszutek Wilk
  -1 siblings, 0 replies; 30+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-03-08 16:59 UTC (permalink / raw)
  To: Albert Herranz; +Cc: linux-usb, linuxppc-dev, linux-kernel, x86, linux-ia64

On Sun, Mar 07, 2010 at 01:11:46PM +0100, Albert Herranz wrote:
> The current SWIOTLB code uses a default of 64MB for the IO TLB area.
> This size can be influenced using a kernel command line parameter "swiotlb".
> Unfortunately, the parsing of the kernel command line is done _after_ the
> swiotlb is initialized on some architectures.

Why can't it be moved up? I mean move the parsing of the kernel
parameters before the PCI subsystem?
> 
> This patch adds a new function swiotlb_set_default_size() which can be used
> before swiotlb_init() to indicate the desired IO TLB area size in bytes.
> 
> This will be used later to implement a smaller IO TLB on the Nintendo Wii
> video game console which just comes with 24MB + 64MB of RAM.

Use the io_tlb_nslabs, which is what swiotlb_init_with_default_size uses
(the passed in argument is only used if io_tlb_nslabs is not set).


> 
> Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
> CC: linuxppc-dev@lists.ozlabs.org
> CC: linux-kernel@vger.kernel.org
> CC: x86@kernel.org
> CC: linux-ia64@vger.kernel.org
> ---
>  include/linux/swiotlb.h |    2 ++
>  lib/swiotlb.c           |   27 ++++++++++++++++++++++++++-
>  2 files changed, 28 insertions(+), 1 deletions(-)
> 
> diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
> index 3954228..2af6a45 100644
> --- a/include/linux/swiotlb.h
> +++ b/include/linux/swiotlb.h
> @@ -22,6 +22,8 @@ extern int swiotlb_force;
>   */
>  #define IO_TLB_SHIFT 11
>  
> +extern size_t __init swiotlb_set_default_size(size_t size);
> +
>  extern void swiotlb_init(int verbose);
>  
>  extern void *swiotlb_alloc_boot(size_t bytes, unsigned long nslabs);
> diff --git a/lib/swiotlb.c b/lib/swiotlb.c
> index 8f2dad9..c99512d 100644
> --- a/lib/swiotlb.c
> +++ b/lib/swiotlb.c
> @@ -73,6 +73,11 @@ static char *io_tlb_start, *io_tlb_end;
>  static unsigned long io_tlb_nslabs;
>  
>  /*
> + * Default size for the IO TLB (64MB).
> + */
> +static __initdata size_t io_tlb_default_size = 64 * (1<<20);
> +
> +/*
>   * When the IOMMU overflows we return a fallback buffer. This sets the size.
>   */
>  static unsigned long io_tlb_overflow = 32*1024;
> @@ -117,6 +122,26 @@ setup_io_tlb_npages(char *str)
>  __setup("swiotlb=", setup_io_tlb_npages);
>  /* make io_tlb_overflow tunable too? */
>  
> +/**
> + * swiotlb_set_default_size() - set the default size for the IO TLB
> + * @size:	size in bytes of the IO TLB
> + *
> + * A platform can use this function to change the default size of the
> + * IO TLB when the default of 64MB is not suitable.
> + * This function must be called before swiotlb_init().
> + *
> + * Note that on some platforms this is the only way to influence the
> + * size of the IO TLB, as the command line may be parsed _after_ the
> + * IO TLB is initialized.
> + */
> +size_t __init swiotlb_set_default_size(size_t size)
> +{
> +	size_t previous_size = io_tlb_default_size;
> +
> +	io_tlb_default_size = size;
> +	return previous_size;
> +}
> +
>  void * __weak __init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
>  {
>  	return alloc_bootmem_low_pages(size);
> @@ -193,7 +218,7 @@ swiotlb_init_with_default_size(size_t default_size, int verbose)
>  void __init
>  swiotlb_init(int verbose)
>  {
> -	swiotlb_init_with_default_size(64 * (1<<20), verbose);	/* default to 64MB */
> +	swiotlb_init_with_default_size(io_tlb_default_size, verbose);
>  }
>  
>  /*
> -- 
> 1.6.3.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [LKML] [RFC PATCH v3 05/11] swiotlb: add swiotlb_set_default_size()
@ 2010-03-08 16:59     ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 30+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-03-08 16:59 UTC (permalink / raw)
  To: Albert Herranz; +Cc: x86, linux-ia64, linux-usb, linuxppc-dev, linux-kernel

On Sun, Mar 07, 2010 at 01:11:46PM +0100, Albert Herranz wrote:
> The current SWIOTLB code uses a default of 64MB for the IO TLB area.
> This size can be influenced using a kernel command line parameter "swiotlb".
> Unfortunately, the parsing of the kernel command line is done _after_ the
> swiotlb is initialized on some architectures.

Why can't it be moved up? I mean move the parsing of the kernel
parameters before the PCI subsystem?
> 
> This patch adds a new function swiotlb_set_default_size() which can be used
> before swiotlb_init() to indicate the desired IO TLB area size in bytes.
> 
> This will be used later to implement a smaller IO TLB on the Nintendo Wii
> video game console which just comes with 24MB + 64MB of RAM.

Use the io_tlb_nslabs, which is what swiotlb_init_with_default_size uses
(the passed in argument is only used if io_tlb_nslabs is not set).


> 
> Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
> CC: linuxppc-dev@lists.ozlabs.org
> CC: linux-kernel@vger.kernel.org
> CC: x86@kernel.org
> CC: linux-ia64@vger.kernel.org
> ---
>  include/linux/swiotlb.h |    2 ++
>  lib/swiotlb.c           |   27 ++++++++++++++++++++++++++-
>  2 files changed, 28 insertions(+), 1 deletions(-)
> 
> diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
> index 3954228..2af6a45 100644
> --- a/include/linux/swiotlb.h
> +++ b/include/linux/swiotlb.h
> @@ -22,6 +22,8 @@ extern int swiotlb_force;
>   */
>  #define IO_TLB_SHIFT 11
>  
> +extern size_t __init swiotlb_set_default_size(size_t size);
> +
>  extern void swiotlb_init(int verbose);
>  
>  extern void *swiotlb_alloc_boot(size_t bytes, unsigned long nslabs);
> diff --git a/lib/swiotlb.c b/lib/swiotlb.c
> index 8f2dad9..c99512d 100644
> --- a/lib/swiotlb.c
> +++ b/lib/swiotlb.c
> @@ -73,6 +73,11 @@ static char *io_tlb_start, *io_tlb_end;
>  static unsigned long io_tlb_nslabs;
>  
>  /*
> + * Default size for the IO TLB (64MB).
> + */
> +static __initdata size_t io_tlb_default_size = 64 * (1<<20);
> +
> +/*
>   * When the IOMMU overflows we return a fallback buffer. This sets the size.
>   */
>  static unsigned long io_tlb_overflow = 32*1024;
> @@ -117,6 +122,26 @@ setup_io_tlb_npages(char *str)
>  __setup("swiotlb=", setup_io_tlb_npages);
>  /* make io_tlb_overflow tunable too? */
>  
> +/**
> + * swiotlb_set_default_size() - set the default size for the IO TLB
> + * @size:	size in bytes of the IO TLB
> + *
> + * A platform can use this function to change the default size of the
> + * IO TLB when the default of 64MB is not suitable.
> + * This function must be called before swiotlb_init().
> + *
> + * Note that on some platforms this is the only way to influence the
> + * size of the IO TLB, as the command line may be parsed _after_ the
> + * IO TLB is initialized.
> + */
> +size_t __init swiotlb_set_default_size(size_t size)
> +{
> +	size_t previous_size = io_tlb_default_size;
> +
> +	io_tlb_default_size = size;
> +	return previous_size;
> +}
> +
>  void * __weak __init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
>  {
>  	return alloc_bootmem_low_pages(size);
> @@ -193,7 +218,7 @@ swiotlb_init_with_default_size(size_t default_size, int verbose)
>  void __init
>  swiotlb_init(int verbose)
>  {
> -	swiotlb_init_with_default_size(64 * (1<<20), verbose);	/* default to 64MB */
> +	swiotlb_init_with_default_size(io_tlb_default_size, verbose);
>  }
>  
>  /*
> -- 
> 1.6.3.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [LKML] [RFC PATCH v3 05/11] swiotlb: add
@ 2010-03-08 16:59     ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 30+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-03-08 16:59 UTC (permalink / raw)
  To: Albert Herranz; +Cc: linux-usb, linuxppc-dev, linux-kernel, x86, linux-ia64

On Sun, Mar 07, 2010 at 01:11:46PM +0100, Albert Herranz wrote:
> The current SWIOTLB code uses a default of 64MB for the IO TLB area.
> This size can be influenced using a kernel command line parameter "swiotlb".
> Unfortunately, the parsing of the kernel command line is done _after_ the
> swiotlb is initialized on some architectures.

Why can't it be moved up? I mean move the parsing of the kernel
parameters before the PCI subsystem?
> 
> This patch adds a new function swiotlb_set_default_size() which can be used
> before swiotlb_init() to indicate the desired IO TLB area size in bytes.
> 
> This will be used later to implement a smaller IO TLB on the Nintendo Wii
> video game console which just comes with 24MB + 64MB of RAM.

Use the io_tlb_nslabs, which is what swiotlb_init_with_default_size uses
(the passed in argument is only used if io_tlb_nslabs is not set).


> 
> Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
> CC: linuxppc-dev@lists.ozlabs.org
> CC: linux-kernel@vger.kernel.org
> CC: x86@kernel.org
> CC: linux-ia64@vger.kernel.org
> ---
>  include/linux/swiotlb.h |    2 ++
>  lib/swiotlb.c           |   27 ++++++++++++++++++++++++++-
>  2 files changed, 28 insertions(+), 1 deletions(-)
> 
> diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
> index 3954228..2af6a45 100644
> --- a/include/linux/swiotlb.h
> +++ b/include/linux/swiotlb.h
> @@ -22,6 +22,8 @@ extern int swiotlb_force;
>   */
>  #define IO_TLB_SHIFT 11
>  
> +extern size_t __init swiotlb_set_default_size(size_t size);
> +
>  extern void swiotlb_init(int verbose);
>  
>  extern void *swiotlb_alloc_boot(size_t bytes, unsigned long nslabs);
> diff --git a/lib/swiotlb.c b/lib/swiotlb.c
> index 8f2dad9..c99512d 100644
> --- a/lib/swiotlb.c
> +++ b/lib/swiotlb.c
> @@ -73,6 +73,11 @@ static char *io_tlb_start, *io_tlb_end;
>  static unsigned long io_tlb_nslabs;
>  
>  /*
> + * Default size for the IO TLB (64MB).
> + */
> +static __initdata size_t io_tlb_default_size = 64 * (1<<20);
> +
> +/*
>   * When the IOMMU overflows we return a fallback buffer. This sets the size.
>   */
>  static unsigned long io_tlb_overflow = 32*1024;
> @@ -117,6 +122,26 @@ setup_io_tlb_npages(char *str)
>  __setup("swiotlb=", setup_io_tlb_npages);
>  /* make io_tlb_overflow tunable too? */
>  
> +/**
> + * swiotlb_set_default_size() - set the default size for the IO TLB
> + * @size:	size in bytes of the IO TLB
> + *
> + * A platform can use this function to change the default size of the
> + * IO TLB when the default of 64MB is not suitable.
> + * This function must be called before swiotlb_init().
> + *
> + * Note that on some platforms this is the only way to influence the
> + * size of the IO TLB, as the command line may be parsed _after_ the
> + * IO TLB is initialized.
> + */
> +size_t __init swiotlb_set_default_size(size_t size)
> +{
> +	size_t previous_size = io_tlb_default_size;
> +
> +	io_tlb_default_size = size;
> +	return previous_size;
> +}
> +
>  void * __weak __init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
>  {
>  	return alloc_bootmem_low_pages(size);
> @@ -193,7 +218,7 @@ swiotlb_init_with_default_size(size_t default_size, int verbose)
>  void __init
>  swiotlb_init(int verbose)
>  {
> -	swiotlb_init_with_default_size(64 * (1<<20), verbose);	/* default to 64MB */
> +	swiotlb_init_with_default_size(io_tlb_default_size, verbose);
>  }
>  
>  /*
> -- 
> 1.6.3.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [LKML] [RFC PATCH v3 04/11] swiotlb: support NOT_COHERENT_CACHE PowerPC platforms
  2010-03-08 16:55     ` [LKML] [RFC PATCH v3 04/11] swiotlb: support NOT_COHERENT_CACHE PowerPC platforms Konrad Rzeszutek Wilk
  (?)
@ 2010-03-09 18:07       ` Albert Herranz
  -1 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-09 18:07 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: linux-usb, linuxppc-dev, linux-kernel, x86, linux-ia64

Konrad Rzeszutek Wilk wrote:
> Hey Albert,
> 
> I've been doing some posting in this area to split the physical / bus
> address translation so that multiple platforms can utilize it. I was
> wondering if it makes sense to utilize some of those concepts (ie, extend it
> for DMA coherency) for your code:
> 
> https://lists.linux-foundation.org/pipermail/iommu/2010-February/002066.html
> 
> And here is the git tree that goes on top of those patches:
> git://git.kernel.org/pub/scm/linux/kernel/git/konrad/swiotlb-2.6.git xen-swiotlb-0.5
> 

Hi Konrad,

Thanks for your comments.

In my case, I'd like to re-use as much code from swiotlb as possible.
Adding a few function calls at strategic spots (which are optimized out for cache coherent platforms) to maintain cache coherency is currently enough for me if that's acceptable.
A more general approach would involve making swiotlb_bounce() platform-dependent (or at least the actual code for copying the buffers), and re-implementing map_page, sync_single and map_sg at the platform DMA code again.

I've whipped through your patches. If I undestood them, you make available a kind of swiotlb "library" core on top of which you can build alternate swiotlb-based dma ops.
Wouldn't it be a good idea to split the "library" code from the default swiotlb dma ops?
A(n embedded) platform may just want the "library" code to implement its own dma ops, without having to pay for the extra default swiotlb dma ops implementation.

Thanks,
Albert


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

* Re: [LKML] [RFC PATCH v3 04/11] swiotlb: support NOT_COHERENT_CACHE PowerPC platforms
@ 2010-03-09 18:07       ` Albert Herranz
  0 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-09 18:07 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: x86, linux-ia64, linux-usb, linuxppc-dev, linux-kernel

Konrad Rzeszutek Wilk wrote:
> Hey Albert,
> 
> I've been doing some posting in this area to split the physical / bus
> address translation so that multiple platforms can utilize it. I was
> wondering if it makes sense to utilize some of those concepts (ie, extend it
> for DMA coherency) for your code:
> 
> https://lists.linux-foundation.org/pipermail/iommu/2010-February/002066.html
> 
> And here is the git tree that goes on top of those patches:
> git://git.kernel.org/pub/scm/linux/kernel/git/konrad/swiotlb-2.6.git xen-swiotlb-0.5
> 

Hi Konrad,

Thanks for your comments.

In my case, I'd like to re-use as much code from swiotlb as possible.
Adding a few function calls at strategic spots (which are optimized out for cache coherent platforms) to maintain cache coherency is currently enough for me if that's acceptable.
A more general approach would involve making swiotlb_bounce() platform-dependent (or at least the actual code for copying the buffers), and re-implementing map_page, sync_single and map_sg at the platform DMA code again.

I've whipped through your patches. If I undestood them, you make available a kind of swiotlb "library" core on top of which you can build alternate swiotlb-based dma ops.
Wouldn't it be a good idea to split the "library" code from the default swiotlb dma ops?
A(n embedded) platform may just want the "library" code to implement its own dma ops, without having to pay for the extra default swiotlb dma ops implementation.

Thanks,
Albert

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

* Re: [LKML] [RFC PATCH v3 04/11] swiotlb: support NOT_COHERENT_CACHE
@ 2010-03-09 18:07       ` Albert Herranz
  0 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-09 18:07 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: linux-usb, linuxppc-dev, linux-kernel, x86, linux-ia64

Konrad Rzeszutek Wilk wrote:
> Hey Albert,
> 
> I've been doing some posting in this area to split the physical / bus
> address translation so that multiple platforms can utilize it. I was
> wondering if it makes sense to utilize some of those concepts (ie, extend it
> for DMA coherency) for your code:
> 
> https://lists.linux-foundation.org/pipermail/iommu/2010-February/002066.html
> 
> And here is the git tree that goes on top of those patches:
> git://git.kernel.org/pub/scm/linux/kernel/git/konrad/swiotlb-2.6.git xen-swiotlb-0.5
> 

Hi Konrad,

Thanks for your comments.

In my case, I'd like to re-use as much code from swiotlb as possible.
Adding a few function calls at strategic spots (which are optimized out for cache coherent platforms) to maintain cache coherency is currently enough for me if that's acceptable.
A more general approach would involve making swiotlb_bounce() platform-dependent (or at least the actual code for copying the buffers), and re-implementing map_page, sync_single and map_sg at the platform DMA code again.

I've whipped through your patches. If I undestood them, you make available a kind of swiotlb "library" core on top of which you can build alternate swiotlb-based dma ops.
Wouldn't it be a good idea to split the "library" code from the default swiotlb dma ops?
A(n embedded) platform may just want the "library" code to implement its own dma ops, without having to pay for the extra default swiotlb dma ops implementation.

Thanks,
Albert


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

* Re: [LKML] [RFC PATCH v3 05/11] swiotlb: add swiotlb_set_default_size()
  2010-03-08 16:59     ` [LKML] [RFC PATCH v3 05/11] swiotlb: add swiotlb_set_default_size() Konrad Rzeszutek Wilk
  (?)
@ 2010-03-09 18:38       ` Albert Herranz
  -1 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-09 18:38 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: linux-usb, linuxppc-dev, linux-kernel, x86, linux-ia64

Konrad Rzeszutek Wilk wrote:
> On Sun, Mar 07, 2010 at 01:11:46PM +0100, Albert Herranz wrote:
>> The current SWIOTLB code uses a default of 64MB for the IO TLB area.
>> This size can be influenced using a kernel command line parameter "swiotlb".
>> Unfortunately, the parsing of the kernel command line is done _after_ the
>> swiotlb is initialized on some architectures.
> 
> Why can't it be moved up? I mean move the parsing of the kernel
> parameters before the PCI subsystem?

(In my case there's no PCI subsystem, this is an embedded platform without PCI support).

Currently, in the PowerPC tree a platform wanting to use the swiotlb just sets the global ppc_swiotlb_enable variable to true in its setup_arch() function.
The PowerPC setup code then calls swiotlb_init(1) just after setup_arch() when SWIOTLB and ppc_swiotlb_enable is true.
At this point the kernel command line is not yet parsed.

So, at least in PowerPC linux, the early swiotlb initialization is not influenced by the kernel command line.

Maybe switching swiotlb from __setup to early_param would help too.

>> This patch adds a new function swiotlb_set_default_size() which can be used
>> before swiotlb_init() to indicate the desired IO TLB area size in bytes.
>>
>> This will be used later to implement a smaller IO TLB on the Nintendo Wii
>> video game console which just comes with 24MB + 64MB of RAM.
> 
> Use the io_tlb_nslabs, which is what swiotlb_init_with_default_size uses
> (the passed in argument is only used if io_tlb_nslabs is not set).
> 

True, thanks.

Cheers,
Albert


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

* Re: [LKML] [RFC PATCH v3 05/11] swiotlb: add swiotlb_set_default_size()
@ 2010-03-09 18:38       ` Albert Herranz
  0 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-09 18:38 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: x86, linux-ia64, linux-usb, linuxppc-dev, linux-kernel

Konrad Rzeszutek Wilk wrote:
> On Sun, Mar 07, 2010 at 01:11:46PM +0100, Albert Herranz wrote:
>> The current SWIOTLB code uses a default of 64MB for the IO TLB area.
>> This size can be influenced using a kernel command line parameter "swiotlb".
>> Unfortunately, the parsing of the kernel command line is done _after_ the
>> swiotlb is initialized on some architectures.
> 
> Why can't it be moved up? I mean move the parsing of the kernel
> parameters before the PCI subsystem?

(In my case there's no PCI subsystem, this is an embedded platform without PCI support).

Currently, in the PowerPC tree a platform wanting to use the swiotlb just sets the global ppc_swiotlb_enable variable to true in its setup_arch() function.
The PowerPC setup code then calls swiotlb_init(1) just after setup_arch() when SWIOTLB and ppc_swiotlb_enable is true.
At this point the kernel command line is not yet parsed.

So, at least in PowerPC linux, the early swiotlb initialization is not influenced by the kernel command line.

Maybe switching swiotlb from __setup to early_param would help too.

>> This patch adds a new function swiotlb_set_default_size() which can be used
>> before swiotlb_init() to indicate the desired IO TLB area size in bytes.
>>
>> This will be used later to implement a smaller IO TLB on the Nintendo Wii
>> video game console which just comes with 24MB + 64MB of RAM.
> 
> Use the io_tlb_nslabs, which is what swiotlb_init_with_default_size uses
> (the passed in argument is only used if io_tlb_nslabs is not set).
> 

True, thanks.

Cheers,
Albert

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

* Re: [LKML] [RFC PATCH v3 05/11] swiotlb: add swiotlb_set_default_size()
@ 2010-03-09 18:38       ` Albert Herranz
  0 siblings, 0 replies; 30+ messages in thread
From: Albert Herranz @ 2010-03-09 18:38 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: linux-usb, linuxppc-dev, linux-kernel, x86, linux-ia64

Konrad Rzeszutek Wilk wrote:
> On Sun, Mar 07, 2010 at 01:11:46PM +0100, Albert Herranz wrote:
>> The current SWIOTLB code uses a default of 64MB for the IO TLB area.
>> This size can be influenced using a kernel command line parameter "swiotlb".
>> Unfortunately, the parsing of the kernel command line is done _after_ the
>> swiotlb is initialized on some architectures.
> 
> Why can't it be moved up? I mean move the parsing of the kernel
> parameters before the PCI subsystem?

(In my case there's no PCI subsystem, this is an embedded platform without PCI support).

Currently, in the PowerPC tree a platform wanting to use the swiotlb just sets the global ppc_swiotlb_enable variable to true in its setup_arch() function.
The PowerPC setup code then calls swiotlb_init(1) just after setup_arch() when SWIOTLB and ppc_swiotlb_enable is true.
At this point the kernel command line is not yet parsed.

So, at least in PowerPC linux, the early swiotlb initialization is not influenced by the kernel command line.

Maybe switching swiotlb from __setup to early_param would help too.

>> This patch adds a new function swiotlb_set_default_size() which can be used
>> before swiotlb_init() to indicate the desired IO TLB area size in bytes.
>>
>> This will be used later to implement a smaller IO TLB on the Nintendo Wii
>> video game console which just comes with 24MB + 64MB of RAM.
> 
> Use the io_tlb_nslabs, which is what swiotlb_init_with_default_size uses
> (the passed in argument is only used if io_tlb_nslabs is not set).
> 

True, thanks.

Cheers,
Albert


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

end of thread, other threads:[~2010-03-09 18:38 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-07 12:11 [RFC PATCH v3 00/11] wii: add usb 2.0 support Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 01/11] powerpc: add per-device dma coherent support Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 02/11] powerpc: add min_direct_dma_addr Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 03/11] swiotbl: add back swiotlb_alloc_boot() Albert Herranz
2010-03-07 12:11   ` Albert Herranz
2010-03-07 12:11   ` Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 04/11] swiotlb: support NOT_COHERENT_CACHE PowerPC platforms Albert Herranz
2010-03-07 12:11   ` Albert Herranz
2010-03-07 12:11   ` Albert Herranz
2010-03-08 16:55   ` [LKML] " Konrad Rzeszutek Wilk
2010-03-08 16:55     ` [LKML] [RFC PATCH v3 04/11] swiotlb: support Konrad Rzeszutek Wilk
2010-03-08 16:55     ` [LKML] [RFC PATCH v3 04/11] swiotlb: support NOT_COHERENT_CACHE PowerPC platforms Konrad Rzeszutek Wilk
2010-03-09 18:07     ` Albert Herranz
2010-03-09 18:07       ` [LKML] [RFC PATCH v3 04/11] swiotlb: support NOT_COHERENT_CACHE Albert Herranz
2010-03-09 18:07       ` [LKML] [RFC PATCH v3 04/11] swiotlb: support NOT_COHERENT_CACHE PowerPC platforms Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 05/11] swiotlb: add swiotlb_set_default_size() Albert Herranz
2010-03-07 12:11   ` Albert Herranz
2010-03-07 12:11   ` Albert Herranz
2010-03-08 16:59   ` [LKML] " Konrad Rzeszutek Wilk
2010-03-08 16:59     ` [LKML] [RFC PATCH v3 05/11] swiotlb: add Konrad Rzeszutek Wilk
2010-03-08 16:59     ` [LKML] [RFC PATCH v3 05/11] swiotlb: add swiotlb_set_default_size() Konrad Rzeszutek Wilk
2010-03-09 18:38     ` Albert Herranz
2010-03-09 18:38       ` Albert Herranz
2010-03-09 18:38       ` Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 06/11] USB: refactor unmap_urb_for_dma/map_urb_for_dma Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 07/11] USB: add HCD_NO_COHERENT_MEM host controller driver flag Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 08/11] wii: have generic dma coherent Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 09/11] wii: add mem2 dma mapping ops Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 10/11] wii: enable swiotlb Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 11/11] wii: hollywood ehci controller support Albert Herranz

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.