All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 00/10] wii: add usb 2.0 support
@ 2010-03-19 18:32 Albert Herranz
  2010-03-19 18:32 ` [PATCH v5 01/10] swiotbl: add back swiotlb_alloc_boot() Albert Herranz
                   ` (10 more replies)
  0 siblings, 11 replies; 17+ messages in thread
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, stern, konrad.wilk

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.

v4 -> v5
- Set the default IO TLB size via the kernel command line.
  This is now possible on PowerPC thanks to a recent patch by Fujita Tomonori.
- swiotlb support for the Wii is now based on top of the swiotlb-0.6
  patches from Konrad Rzeszutek Wilk.
- Keeps using v4 of the USB HCD_NO_COHERENT_MEM patch

Alan: I think you are also working in a patchset to make {un}map_urb_for_dma
remember how the urb was mapped, right?

Albert Herranz (10):
  swiotbl: add back swiotlb_alloc_boot()
  swiotlb: make swiotlb_bounce() __weak
  powerpc: add per-device dma coherent support
  powerpc: add min_direct_dma_addr
  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/powerpc/boot/dts/wii.dts                |    2 +-
 arch/powerpc/boot/wii.c                      |   44 +++
 arch/powerpc/include/asm/device.h            |    1 +
 arch/powerpc/include/asm/dma-mapping.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 |  475 ++++++++++++++++++++++++++
 arch/powerpc/platforms/embedded6xx/wii.c     |    1 +
 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                      |    1 +
 include/linux/usb.h                          |    5 +
 lib/swiotlb.c                                |   12 +-
 20 files changed, 1033 insertions(+), 90 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] 17+ messages in thread

* [PATCH v5 01/10] swiotbl: add back swiotlb_alloc_boot()
  2010-03-19 18:32 [PATCH v5 00/10] wii: add usb 2.0 support Albert Herranz
@ 2010-03-19 18:32 ` Albert Herranz
  2010-03-19 18:32 ` [PATCH v5 02/10] swiotlb: make swiotlb_bounce() __weak Albert Herranz
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk

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>
---
 include/linux/swiotlb.h |    1 +
 lib/swiotlb.c           |   10 ++++++++--
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 8550d6b..c769939 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -54,6 +54,7 @@ extern void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
 			   enum dma_data_direction dir);
 extern void swiotlb_full(struct device *dev, size_t size, int dir, int do_panic);
 
+extern void __init *swiotlb_alloc_boot(size_t bytes, unsigned long nslabs);
 #endif
 
 /* swiotlb.c: dma_ops functions. */
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index c6bfa5d..ab1622a 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -136,6 +136,11 @@ void swiotlb_print_info(void)
 	       (unsigned long long)pend);
 }
 
+void * __weak __init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
+{
+	return alloc_bootmem_low_pages(size);
+}
+
 /*
  * Statically reserve bounce buffer space and initialize bounce buffer data
  * structures for the software IO TLB used to implement the DMA API.
@@ -155,7 +160,7 @@ swiotlb_init_with_default_size(size_t default_size, int verbose)
 	/*
 	 * Get IO TLB memory from the low pages
 	 */
-	swiotlb_bk_start = alloc_bootmem_low_pages(bytes);
+	swiotlb_bk_start = swiotlb_alloc_boot(bytes, swiotlb_bk_nslabs);
 	if (!swiotlb_bk_start)
 		panic("Cannot allocate SWIOTLB buffer");
 	swiotlb_bk_end = swiotlb_bk_start + bytes;
@@ -175,7 +180,8 @@ swiotlb_init_with_default_size(size_t default_size, int verbose)
 	/*
 	 * Get the overflow emergency buffer
 	 */
-	swiotlb_bk_overflow_buffer = alloc_bootmem_low(swiotlb_bk_overflow);
+	swiotlb_bk_overflow_buffer = swiotlb_alloc_boot(swiotlb_bk_overflow,
+							swiotlb_bk_nslabs);
 	if (!swiotlb_bk_overflow_buffer)
 		panic("Cannot allocate SWIOTLB overflow buffer!\n");
 	if (verbose)
-- 
1.6.3.3

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

* [PATCH v5 02/10] swiotlb: make swiotlb_bounce() __weak
  2010-03-19 18:32 [PATCH v5 00/10] wii: add usb 2.0 support Albert Herranz
  2010-03-19 18:32 ` [PATCH v5 01/10] swiotbl: add back swiotlb_alloc_boot() Albert Herranz
@ 2010-03-19 18:32 ` Albert Herranz
  2010-03-19 18:32 ` [PATCH v5 03/10] powerpc: add per-device dma coherent support Albert Herranz
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk

This patch converts swiotlb_bounce() into a weak function making it
overloadable by platform support code.

This will be used later to support the Nintendo Wii video game console,
which is a NOT_COHERENT_CACHE platform and requires explicit cache handling
when dealing with the swiotlb bounce buffers.

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
---
 lib/swiotlb.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index ab1622a..9ce5cd2 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -328,7 +328,7 @@ EXPORT_SYMBOL_GPL(is_swiotlb_buffer);
 /*
  * Bounce: copy the swiotlb buffer back to the original dma location
  */
-void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
+void __weak swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
 			   enum dma_data_direction dir)
 {
 	unsigned long pfn = PFN_DOWN(phys);
-- 
1.6.3.3

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

* [PATCH v5 03/10] powerpc: add per-device dma coherent support
  2010-03-19 18:32 [PATCH v5 00/10] wii: add usb 2.0 support Albert Herranz
  2010-03-19 18:32 ` [PATCH v5 01/10] swiotbl: add back swiotlb_alloc_boot() Albert Herranz
  2010-03-19 18:32 ` [PATCH v5 02/10] swiotlb: make swiotlb_bounce() __weak Albert Herranz
@ 2010-03-19 18:32 ` Albert Herranz
  2010-03-19 18:32 ` [PATCH v5 04/10] powerpc: add min_direct_dma_addr Albert Herranz
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk

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] 17+ messages in thread

* [PATCH v5 04/10] powerpc: add min_direct_dma_addr
  2010-03-19 18:32 [PATCH v5 00/10] wii: add usb 2.0 support Albert Herranz
                   ` (2 preceding siblings ...)
  2010-03-19 18:32 ` [PATCH v5 03/10] powerpc: add per-device dma coherent support Albert Herranz
@ 2010-03-19 18:32 ` Albert Herranz
  2010-03-19 18:32 ` [PATCH v5 05/10] USB: refactor unmap_urb_for_dma/map_urb_for_dma Albert Herranz
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk

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] 17+ messages in thread

* [PATCH v5 05/10] USB: refactor unmap_urb_for_dma/map_urb_for_dma
  2010-03-19 18:32 [PATCH v5 00/10] wii: add usb 2.0 support Albert Herranz
                   ` (3 preceding siblings ...)
  2010-03-19 18:32 ` [PATCH v5 04/10] powerpc: add min_direct_dma_addr Albert Herranz
@ 2010-03-19 18:32 ` Albert Herranz
  2010-03-19 18:32 ` [PATCH v5 06/10] USB: add HCD_NO_COHERENT_MEM host controller driver flag Albert Herranz
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk

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] 17+ messages in thread

* [PATCH v5 06/10] USB: add HCD_NO_COHERENT_MEM host controller driver flag
  2010-03-19 18:32 [PATCH v5 00/10] wii: add usb 2.0 support Albert Herranz
                   ` (4 preceding siblings ...)
  2010-03-19 18:32 ` [PATCH v5 05/10] USB: refactor unmap_urb_for_dma/map_urb_for_dma Albert Herranz
@ 2010-03-19 18:32 ` Albert Herranz
  2010-03-19 18:32 ` [PATCH v5 07/10] wii: have generic dma coherent Albert Herranz
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk

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] 17+ messages in thread

* [PATCH v5 07/10] wii: have generic dma coherent
  2010-03-19 18:32 [PATCH v5 00/10] wii: add usb 2.0 support Albert Herranz
                   ` (5 preceding siblings ...)
  2010-03-19 18:32 ` [PATCH v5 06/10] USB: add HCD_NO_COHERENT_MEM host controller driver flag Albert Herranz
@ 2010-03-19 18:32 ` Albert Herranz
  2010-03-19 18:32 ` [PATCH v5 08/10] wii: add mem2 dma mapping ops Albert Herranz
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk

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] 17+ messages in thread

* [PATCH v5 08/10] wii: add mem2 dma mapping ops
  2010-03-19 18:32 [PATCH v5 00/10] wii: add usb 2.0 support Albert Herranz
                   ` (6 preceding siblings ...)
  2010-03-19 18:32 ` [PATCH v5 07/10] wii: have generic dma coherent Albert Herranz
@ 2010-03-19 18:32 ` Albert Herranz
  2010-03-19 19:50   ` Konrad Rzeszutek Wilk
  2010-03-19 19:51   ` Konrad Rzeszutek Wilk
  2010-03-19 18:32 ` [PATCH v5 09/10] wii: enable swiotlb Albert Herranz
                   ` (2 subsequent siblings)
  10 siblings, 2 replies; 17+ messages in thread
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk

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                      |   44 +++
 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 |  475 ++++++++++++++++++++++++++
 5 files changed, 546 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..84ce593 100644
--- a/arch/powerpc/boot/wii.c
+++ b/arch/powerpc/boot/wii.c
@@ -30,6 +30,7 @@ BSS_STACK(8192);
 #define MEM2_TOP		(0x10000000 + 64*1024*1024)
 #define FIRMWARE_DEFAULT_SIZE	(12*1024*1024)
 
+#define MEM2_DMA_DEFAULT_SIZE	(512*1024)
 
 struct mipc_infohdr {
 	char magic[3];
@@ -101,6 +102,42 @@ out:
 
 }
 
+static char tmp_cmdline[COMMAND_LINE_SIZE];
+
+static void mem2_fixups(u32 *top, u32 *reg)
+{
+	/* ' mem2_dma=' + nnnnnnn + 'K@0x' + aaaaaaaa */
+	const int max_param_len = 10 + 7 + 4 + 8;
+	void *chosen;
+	u32 dma_base, dma_size;
+	char *p;
+
+	chosen = finddevice("/chosen");
+	if (!chosen)
+		fatal("Can't find chosen node\n");
+
+	/* the MEM2 DMA region must fit within MEM2 */
+	dma_size = MEM2_DMA_DEFAULT_SIZE;
+	if (dma_size > reg[3])
+		dma_size = reg[3];
+	/* reserve the region from the top of MEM2 */
+	*top -= dma_size;
+	dma_base = *top;
+	printf("mem2_dma: %uk@0x%08x\n", dma_size >> 10, dma_base);
+
+	/*
+	 * Finally, add the MEM2 DMA region location information to the
+	 * kernel command line. The wii-dma driver will pick this info up.
+	 */
+	getprop(chosen, "bootargs", tmp_cmdline, COMMAND_LINE_SIZE-1);
+	p = strchr(tmp_cmdline, 0);
+	if (p - tmp_cmdline + max_param_len >= COMMAND_LINE_SIZE)
+		fatal("No space left for mem2_dma param\n");
+
+	sprintf(p, " mem2_dma=%uk@0x%08x", dma_size >> 10, dma_base);
+	setprop_str(chosen, "bootargs", tmp_cmdline);
+}
+
 static void platform_fixups(void)
 {
 	void *mem;
@@ -127,9 +164,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..d7f6cb9
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/wii-dma.c
@@ -0,0 +1,475 @@
+/*
+ * 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.
+ */
+
+/*
+ * 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.
+ */
+
+#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"
+
+/*
+ * 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 __initdata dma_addr_t dma_base, dma_size;
+
+static int __init mem2_setup_parse(char *str)
+{
+	char *p, *q = str;
+
+	dma_size = memparse(q, &p);
+	if (p == q) {
+		pr_err("dma_size expected\n");
+		return -EINVAL;
+	}
+	if (*p != '@') {
+		pr_err("missing @ separator between dma_size and dma_base\n");
+		return -EINVAL;
+	}
+
+	q = p + 1;
+	dma_base = memparse(q, &p);
+	if (p == q) {
+		pr_err("dma_base expected\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+__setup("mem2_dma=", mem2_setup_parse);
+
+static int __init mem2_dma_setup(void)
+{
+	int error;
+
+	BUG_ON(dma_base < lmb_end_of_DRAM());
+	BUG_ON(dma_size == 0);
+
+	error = mem2_dma_init(dma_base, dma_size);
+	if (error)
+		pr_err("error %d during setup\n", error);
+	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);
+
+/*
+ * swiotlb-based DMA ops for MEM2-only devices on the Wii.
+ *
+ */
+
+/*
+ * 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);
+}
+
+/*
+ * Bounce: copy the swiotlb buffer back to the original dma location
+ * This is a platform specific version replacing the generic __weak version.
+ */
+void swiotlb_bounce(phys_addr_t phys, char *dma_buf, size_t size,
+		    enum dma_data_direction dir)
+{
+	void *vaddr = phys_to_virt(phys);
+
+	if (dir == DMA_TO_DEVICE) {
+		memcpy(dma_buf, vaddr, size);
+		__dma_sync(dma_buf, size, dir);
+	} else {
+		__dma_sync(dma_buf, size, dir);
+		memcpy(vaddr, dma_buf, size);
+	}
+}
+
+static dma_addr_t
+mem2_virt_to_bus(struct device *dev, void *address)
+{
+	return phys_to_dma(dev, virt_to_phys(address));
+}
+
+static int
+mem2_dma_mapping_error(struct device *dev, dma_addr_t dma_handle)
+{
+	return dma_handle == mem2_virt_to_bus(dev, swiotlb_bk_overflow_buffer);
+}
+
+static int
+mem2_dma_supported(struct device *dev, u64 mask)
+{
+	return mem2_virt_to_bus(dev, swiotlb_bk_end - 1) <= mask;
+}
+
+/*
+ * 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
+ * from the MEM2 DMA region.
+ */
+
+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(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);
+}
+
+/*
+ * Maps (part of) a page so it can be safely accessed by a device.
+ *
+ * Calls the corresponding dma_direct_ops hook if the page region falls
+ * within MEM2.
+ * Otherwise, a bounce buffer allocated from MEM2 coherent memory is used.
+ */
+static dma_addr_t
+mem2_map_page(struct device *dev, struct page *page, unsigned long offset,
+	      size_t size, enum dma_data_direction dir,
+	      struct dma_attrs *attrs)
+{
+	phys_addr_t phys = page_to_phys(page) + offset;
+	dma_addr_t dma_handle = phys_to_dma(dev, phys);
+	dma_addr_t swiotlb_start_dma;
+	void *map;
+
+	BUG_ON(dir == DMA_NONE);
+
+	if (dma_capable(dev, dma_handle, size) && !swiotlb_force) {
+		return dma_direct_ops.map_page(dev, page, offset, size,
+					       dir, attrs);
+	}
+
+	swiotlb_start_dma = mem2_virt_to_bus(dev, swiotlb_bk_start);
+	map = swiotlb_bk_map_single(dev, phys, swiotlb_start_dma, size, dir);
+	if (!map) {
+		swiotlb_full(dev, size, dir, 1);
+		map = swiotlb_bk_overflow_buffer;
+	}
+
+	dma_handle = mem2_virt_to_bus(dev, map);
+	BUG_ON(!dma_capable(dev, dma_handle, size));
+
+	return dma_handle;
+}
+
+/*
+ * Unmaps (part of) a page previously mapped.
+ *
+ * Calls the corresponding dma_direct_ops hook if the DMA region associated
+ * to the dma handle @dma_handle wasn't bounced.
+ * Otherwise, the associated bounce buffer is de-bounced.
+ */
+static void
+mem2_unmap_page(struct device *dev, dma_addr_t dma_handle, size_t size,
+		enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	swiotlb_unmap_page(dev, dma_handle, size, dir, attrs);
+}
+
+/*
+ * Unmaps a scatter/gather list by unmapping each entry.
+ */
+static void
+mem2_unmap_sg(struct device *dev, struct scatterlist *sgl, int nents,
+	      enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(sgl, sg, nents, i)
+		mem2_unmap_page(dev, sg->dma_address, sg->length, dir, attrs);
+}
+
+/*
+ * Maps a scatter/gather list by mapping each entry.
+ */
+static int
+mem2_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
+	    enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(sgl, sg, nents, i) {
+		sg->dma_length = sg->length;
+		sg->dma_address = mem2_map_page(dev, sg_page(sg), sg->offset,
+						sg->length, dir, attrs);
+		if (mem2_dma_mapping_error(dev, sg->dma_address)) {
+			mem2_unmap_sg(dev, sgl, i, dir, attrs);
+			nents = 0;
+			sgl[nents].dma_length = 0;
+			pr_debug("%s: mem2_map_page error\n", __func__);
+			break;
+		}
+	}
+	return nents;
+}
+
+/*
+ * The sync functions synchronize streaming mode DMA translations
+ * making physical memory consistent before/after a DMA transfer.
+ *
+ * They call the corresponding dma_direct_ops hook if the DMA region
+ * associated to the dma handle @dma_handle wasn't bounced.
+ * Otherwise, original DMA buffers and their matching bounce buffers are put
+ * in sync.
+ */
+
+static int
+mem2_sync_range(struct device *dev, dma_addr_t dma_handle,
+		unsigned long offset, size_t size, int dir, int target)
+{
+	phys_addr_t paddr = dma_to_phys(dev, dma_handle) + offset;
+	void *vaddr = phys_to_virt(paddr);
+
+	BUG_ON(dir == DMA_NONE);
+
+	if (is_swiotlb_buffer(paddr)) {
+		swiotlb_bk_sync_single(dev, vaddr, size, dir, target);
+		return 1;
+	}
+	return 0;
+}
+
+static void
+mem2_sync_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+			unsigned long offset, size_t size,
+			enum dma_data_direction dir)
+{
+	int done = mem2_sync_range(dev, dma_handle, offset, size, dir,
+				   SYNC_FOR_CPU);
+	if (!done) {
+		dma_direct_ops.sync_single_range_for_cpu(dev, dma_handle,
+							 offset, size, dir);
+	}
+}
+
+static void
+mem2_sync_range_for_device(struct device *dev, dma_addr_t dma_handle,
+			   unsigned long offset, size_t size,
+			   enum dma_data_direction dir)
+{
+	int done = mem2_sync_range(dev, dma_handle, offset, size, dir,
+				   SYNC_FOR_DEVICE);
+	if (!done) {
+		dma_direct_ops.sync_single_range_for_device(dev, dma_handle,
+							    offset, size, dir);
+	}
+}
+
+static void
+mem2_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl, int nents,
+		     enum dma_data_direction dir)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(sgl, sg, nents, i) {
+		mem2_sync_range_for_cpu(dev, sg_dma_address(sg), sg->offset,
+					sg_dma_len(sg), dir);
+	}
+}
+
+static void
+mem2_sync_sg_for_device(struct device *dev, struct scatterlist *sgl, int nents,
+			enum dma_data_direction dir)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(sgl, sg, nents, i) {
+		mem2_sync_range_for_device(dev, sg_dma_address(sg), sg->offset,
+					   sg_dma_len(sg), dir);
+	}
+}
+
+/*
+ * 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 = mem2_map_sg,
+	.unmap_sg = mem2_unmap_sg,
+	.dma_supported = mem2_dma_supported,
+	.map_page = mem2_map_page,
+	.unmap_page = mem2_unmap_page,
+	.sync_single_range_for_cpu = mem2_sync_range_for_cpu,
+	.sync_single_range_for_device = mem2_sync_range_for_device,
+	.sync_sg_for_cpu = mem2_sync_sg_for_cpu,
+	.sync_sg_for_device = mem2_sync_sg_for_device,
+	.mapping_error = mem2_dma_mapping_error,
+};
-- 
1.6.3.3

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

* [PATCH v5 09/10] wii: enable swiotlb
  2010-03-19 18:32 [PATCH v5 00/10] wii: add usb 2.0 support Albert Herranz
                   ` (7 preceding siblings ...)
  2010-03-19 18:32 ` [PATCH v5 08/10] wii: add mem2 dma mapping ops Albert Herranz
@ 2010-03-19 18:32 ` Albert Herranz
  2010-03-19 18:32 ` [PATCH v5 10/10] wii: hollywood ehci controller support Albert Herranz
  2010-03-19 19:01 ` [PATCH v5 00/10] wii: add usb 2.0 support Alan Stern
  10 siblings, 0 replies; 17+ messages in thread
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk

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/boot/dts/wii.dts            |    2 +-
 arch/powerpc/platforms/embedded6xx/wii.c |    1 +
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/boot/dts/wii.dts b/arch/powerpc/boot/dts/wii.dts
index 77528c9..92b8ca6 100644
--- a/arch/powerpc/boot/dts/wii.dts
+++ b/arch/powerpc/boot/dts/wii.dts
@@ -29,7 +29,7 @@
 	#size-cells = <1>;
 
 	chosen {
-		bootargs = "root=/dev/mmcblk0p2 rootwait udbg-immortal";
+		bootargs = "root=/dev/mmcblk0p2 swiotlb=512 rootwait udbg-immortal";
 	};
 
 	memory {
diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c
index 57e5b60..e63c5c8 100644
--- a/arch/powerpc/platforms/embedded6xx/wii.c
+++ b/arch/powerpc/platforms/embedded6xx/wii.c
@@ -164,6 +164,7 @@ static void __init wii_setup_arch(void)
 		clrbits32(hw_gpio + HW_GPIO_OUT(0),
 			  HW_GPIO_SLOT_LED | HW_GPIO_SENSOR_BAR);
 	}
+	ppc_swiotlb_enable = 1;
 }
 
 static void wii_restart(char *cmd)
-- 
1.6.3.3

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

* [PATCH v5 10/10] wii: hollywood ehci controller support
  2010-03-19 18:32 [PATCH v5 00/10] wii: add usb 2.0 support Albert Herranz
                   ` (8 preceding siblings ...)
  2010-03-19 18:32 ` [PATCH v5 09/10] wii: enable swiotlb Albert Herranz
@ 2010-03-19 18:32 ` Albert Herranz
  2010-03-19 19:01 ` [PATCH v5 00/10] wii: add usb 2.0 support Alan Stern
  10 siblings, 0 replies; 17+ messages in thread
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
  To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk

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] 17+ messages in thread

* Re: [PATCH v5 00/10] wii: add usb 2.0 support
  2010-03-19 18:32 [PATCH v5 00/10] wii: add usb 2.0 support Albert Herranz
                   ` (9 preceding siblings ...)
  2010-03-19 18:32 ` [PATCH v5 10/10] wii: hollywood ehci controller support Albert Herranz
@ 2010-03-19 19:01 ` Alan Stern
  2010-03-19 19:13   ` Albert Herranz
  10 siblings, 1 reply; 17+ messages in thread
From: Alan Stern @ 2010-03-19 19:01 UTC (permalink / raw)
  To: Albert Herranz; +Cc: iommu, linux-usb, linuxppc-dev, konrad.wilk

On Fri, 19 Mar 2010, Albert Herranz wrote:

> Alan: I think you are also working in a patchset to make {un}map_urb_for_dma
> remember how the urb was mapped, right?

Yes; you can see an initial version here:

	http://marc.info/?l=linux-usb&m=126901183419219&w=2

This is a bug fix, so it's likely to be merged before your work.

It's a messy situation, with two people changing the same code at the
same time.  I think the best approach will be to wait until the bug-fix
patch is tested and accepted; then I can create a version of your 5/10
and 6/10 patches adding HCD_NO_COHERENT_MEM and the corresponding
behavior.  That can stand by itself, and once it is accepted the rest
of your series should go through with no difficulty (at least, no
difficulties involving the USB core!).

Alan Stern

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

* Re: [PATCH v5 00/10] wii: add usb 2.0 support
  2010-03-19 19:01 ` [PATCH v5 00/10] wii: add usb 2.0 support Alan Stern
@ 2010-03-19 19:13   ` Albert Herranz
  0 siblings, 0 replies; 17+ messages in thread
From: Albert Herranz @ 2010-03-19 19:13 UTC (permalink / raw)
  To: Alan Stern; +Cc: iommu, linux-usb, linuxppc-dev, konrad.wilk

Alan Stern wrote:
>> Alan: I think you are also working in a patchset to make {un}map_urb_for_dma
>> remember how the urb was mapped, right?
> 
> Yes; you can see an initial version here:
> 
> 	http://marc.info/?l=linux-usb&m=126901183419219&w=2
> 
> This is a bug fix, so it's likely to be merged before your work.
> 
> It's a messy situation, with two people changing the same code at the
> same time.  I think the best approach will be to wait until the bug-fix
> patch is tested and accepted; then I can create a version of your 5/10
> and 6/10 patches adding HCD_NO_COHERENT_MEM and the corresponding
> behavior.  That can stand by itself, and once it is accepted the rest
> of your series should go through with no difficulty (at least, no
> difficulties involving the USB core!).

Agreed. I'll keep an eye on these developments.

> 
> Alan Stern
> 

Thanks a lot,
Albert

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

* Re: [PATCH v5 08/10] wii: add mem2 dma mapping ops
  2010-03-19 18:32 ` [PATCH v5 08/10] wii: add mem2 dma mapping ops Albert Herranz
@ 2010-03-19 19:50   ` Konrad Rzeszutek Wilk
  2010-03-20  0:59     ` Albert Herranz
  2010-03-19 19:51   ` Konrad Rzeszutek Wilk
  1 sibling, 1 reply; 17+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-03-19 19:50 UTC (permalink / raw)
  To: Albert Herranz; +Cc: iommu, linux-usb, linuxppc-dev

> +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);

Can you make them EXPORT_SYMBOL_GPL?
> +
> +/**
> + * 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);

Ditto..
> +
> +/*
> + * swiotlb-based DMA ops for MEM2-only devices on the Wii.
> + *
> + */
> +
> +/*
> + * 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);
> +}
> +
> +/*
> + * Bounce: copy the swiotlb buffer back to the original dma location
> + * This is a platform specific version replacing the generic __weak version.
> + */
> +void swiotlb_bounce(phys_addr_t phys, char *dma_buf, size_t size,
> +		    enum dma_data_direction dir)
> +{
> +	void *vaddr = phys_to_virt(phys);
> +
> +	if (dir == DMA_TO_DEVICE) {
> +		memcpy(dma_buf, vaddr, size);
> +		__dma_sync(dma_buf, size, dir);
> +	} else {
> +		__dma_sync(dma_buf, size, dir);
> +		memcpy(vaddr, dma_buf, size);
> +	}
> +}
> +
> +static dma_addr_t
> +mem2_virt_to_bus(struct device *dev, void *address)
> +{
> +	return phys_to_dma(dev, virt_to_phys(address));
> +}
> +
> +static int
> +mem2_dma_mapping_error(struct device *dev, dma_addr_t dma_handle)
> +{
> +	return dma_handle == mem2_virt_to_bus(dev, swiotlb_bk_overflow_buffer);
> +}
> +
> +static int
> +mem2_dma_supported(struct device *dev, u64 mask)
> +{
> +	return mem2_virt_to_bus(dev, swiotlb_bk_end - 1) <= mask;
> +}
> +
> +/*
> + * 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
> + * from the MEM2 DMA region.
> + */
> +
> +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(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);
> +}
> +
> +/*
> + * Maps (part of) a page so it can be safely accessed by a device.
> + *
> + * Calls the corresponding dma_direct_ops hook if the page region falls
> + * within MEM2.
> + * Otherwise, a bounce buffer allocated from MEM2 coherent memory is used.
> + */
> +static dma_addr_t
> +mem2_map_page(struct device *dev, struct page *page, unsigned long offset,
> +	      size_t size, enum dma_data_direction dir,
> +	      struct dma_attrs *attrs)
> +{
> +	phys_addr_t phys = page_to_phys(page) + offset;
> +	dma_addr_t dma_handle = phys_to_dma(dev, phys);
> +	dma_addr_t swiotlb_start_dma;
> +	void *map;
> +
> +	BUG_ON(dir == DMA_NONE);
> +
> +	if (dma_capable(dev, dma_handle, size) && !swiotlb_force) {
> +		return dma_direct_ops.map_page(dev, page, offset, size,
> +					       dir, attrs);
> +	}
> +
> +	swiotlb_start_dma = mem2_virt_to_bus(dev, swiotlb_bk_start);
> +	map = swiotlb_bk_map_single(dev, phys, swiotlb_start_dma, size, dir);
> +	if (!map) {
> +		swiotlb_full(dev, size, dir, 1);
> +		map = swiotlb_bk_overflow_buffer;
> +	}
> +
> +	dma_handle = mem2_virt_to_bus(dev, map);
> +	BUG_ON(!dma_capable(dev, dma_handle, size));
> +
> +	return dma_handle;
> +}
> +
> +/*
> + * Unmaps (part of) a page previously mapped.
> + *
> + * Calls the corresponding dma_direct_ops hook if the DMA region associated
> + * to the dma handle @dma_handle wasn't bounced.
> + * Otherwise, the associated bounce buffer is de-bounced.
> + */
> +static void
> +mem2_unmap_page(struct device *dev, dma_addr_t dma_handle, size_t size,
> +		enum dma_data_direction dir, struct dma_attrs *attrs)
> +{
> +	swiotlb_unmap_page(dev, dma_handle, size, dir, attrs);
> +}
> +
> +/*
> + * Unmaps a scatter/gather list by unmapping each entry.
> + */
> +static void
> +mem2_unmap_sg(struct device *dev, struct scatterlist *sgl, int nents,
> +	      enum dma_data_direction dir, struct dma_attrs *attrs)
> +{
> +	struct scatterlist *sg;
> +	int i;
> +
> +	for_each_sg(sgl, sg, nents, i)
> +		mem2_unmap_page(dev, sg->dma_address, sg->length, dir, attrs);
> +}
> +
> +/*
> + * Maps a scatter/gather list by mapping each entry.
> + */
> +static int
> +mem2_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
> +	    enum dma_data_direction dir, struct dma_attrs *attrs)
> +{
> +	struct scatterlist *sg;
> +	int i;
> +
> +	for_each_sg(sgl, sg, nents, i) {
> +		sg->dma_length = sg->length;
> +		sg->dma_address = mem2_map_page(dev, sg_page(sg), sg->offset,
> +						sg->length, dir, attrs);
> +		if (mem2_dma_mapping_error(dev, sg->dma_address)) {
> +			mem2_unmap_sg(dev, sgl, i, dir, attrs);
> +			nents = 0;
> +			sgl[nents].dma_length = 0;
> +			pr_debug("%s: mem2_map_page error\n", __func__);

Maybe use 'dev_err(dev," mem2..." ?

> +			break;
> +		}
> +	}
> +	return nents;
> +}
> +
> +/*
> + * The sync functions synchronize streaming mode DMA translations
> + * making physical memory consistent before/after a DMA transfer.
> + *
> + * They call the corresponding dma_direct_ops hook if the DMA region
> + * associated to the dma handle @dma_handle wasn't bounced.
> + * Otherwise, original DMA buffers and their matching bounce buffers are put
> + * in sync.
> + */
> +
> +static int
> +mem2_sync_range(struct device *dev, dma_addr_t dma_handle,
> +		unsigned long offset, size_t size, int dir, int target)
> +{
> +	phys_addr_t paddr = dma_to_phys(dev, dma_handle) + offset;
> +	void *vaddr = phys_to_virt(paddr);
> +
> +	BUG_ON(dir == DMA_NONE);
> +
> +	if (is_swiotlb_buffer(paddr)) {
> +		swiotlb_bk_sync_single(dev, vaddr, size, dir, target);
> +		return 1;
> +	}
> +	return 0;
> +}
> +
> +static void
> +mem2_sync_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
> +			unsigned long offset, size_t size,
> +			enum dma_data_direction dir)
> +{
> +	int done = mem2_sync_range(dev, dma_handle, offset, size, dir,
> +				   SYNC_FOR_CPU);
> +	if (!done) {
> +		dma_direct_ops.sync_single_range_for_cpu(dev, dma_handle,
> +							 offset, size, dir);
> +	}
> +}
> +
> +static void
> +mem2_sync_range_for_device(struct device *dev, dma_addr_t dma_handle,
> +			   unsigned long offset, size_t size,
> +			   enum dma_data_direction dir)
> +{
> +	int done = mem2_sync_range(dev, dma_handle, offset, size, dir,
> +				   SYNC_FOR_DEVICE);
> +	if (!done) {
> +		dma_direct_ops.sync_single_range_for_device(dev, dma_handle,
> +							    offset, size, dir);
> +	}
> +}
> +
> +static void
> +mem2_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl, int nents,
> +		     enum dma_data_direction dir)
> +{
> +	struct scatterlist *sg;
> +	int i;
> +
> +	for_each_sg(sgl, sg, nents, i) {
> +		mem2_sync_range_for_cpu(dev, sg_dma_address(sg), sg->offset,
> +					sg_dma_len(sg), dir);
> +	}
> +}
> +
> +static void
> +mem2_sync_sg_for_device(struct device *dev, struct scatterlist *sgl, int nents,
> +			enum dma_data_direction dir)
> +{
> +	struct scatterlist *sg;
> +	int i;
> +
> +	for_each_sg(sgl, sg, nents, i) {
> +		mem2_sync_range_for_device(dev, sg_dma_address(sg), sg->offset,
> +					   sg_dma_len(sg), dir);
> +	}
> +}
> +
> +/*
> + * 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 = mem2_map_sg,
> +	.unmap_sg = mem2_unmap_sg,
> +	.dma_supported = mem2_dma_supported,
> +	.map_page = mem2_map_page,
> +	.unmap_page = mem2_unmap_page,
> +	.sync_single_range_for_cpu = mem2_sync_range_for_cpu,
> +	.sync_single_range_for_device = mem2_sync_range_for_device,
> +	.sync_sg_for_cpu = mem2_sync_sg_for_cpu,
> +	.sync_sg_for_device = mem2_sync_sg_for_device,
> +	.mapping_error = mem2_dma_mapping_error,
> +};
> -- 
> 1.6.3.3
> 
> _______________________________________________
> iommu mailing list
> iommu@lists.linux-foundation.org
> https://lists.linux-foundation.org/mailman/listinfo/iommu

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

* Re: [PATCH v5 08/10] wii: add mem2 dma mapping ops
  2010-03-19 18:32 ` [PATCH v5 08/10] wii: add mem2 dma mapping ops Albert Herranz
  2010-03-19 19:50   ` Konrad Rzeszutek Wilk
@ 2010-03-19 19:51   ` Konrad Rzeszutek Wilk
  2010-03-20  0:58     ` Albert Herranz
  1 sibling, 1 reply; 17+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-03-19 19:51 UTC (permalink / raw)
  To: Albert Herranz; +Cc: iommu, linux-usb, linuxppc-dev

> +/*
> + * 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;
> +

The space there isn't neccessary.

> +	dma_addr_t dma_base;

I think you need only one of them. You don't seem to use 'base'
> +	void *base;
> +	size_t size;
> +};

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

* Re: [PATCH v5 08/10] wii: add mem2 dma mapping ops
  2010-03-19 19:51   ` Konrad Rzeszutek Wilk
@ 2010-03-20  0:58     ` Albert Herranz
  0 siblings, 0 replies; 17+ messages in thread
From: Albert Herranz @ 2010-03-20  0:58 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk; +Cc: iommu, linux-usb, linuxppc-dev

Konrad Rzeszutek Wilk wrote:
>> +/*
>> + * 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;
>> +
> 
> The space there isn't neccessary.
> 

Yes. Having it or not is just a matter of formatting style taste.

>> +	dma_addr_t dma_base;
> 
> I think you need only one of them. You don't seem to use 'base'
>> +	void *base;
>> +	size_t size;
>> +};
> 

I can even get rid of the whole struct mem2_dma and just use a struct platform_device now that there's no mem2_dma_exit() function.
I'll do that on the next iteration.

Thanks for your comments.

Cheers,
Albert

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

* Re: [PATCH v5 08/10] wii: add mem2 dma mapping ops
  2010-03-19 19:50   ` Konrad Rzeszutek Wilk
@ 2010-03-20  0:59     ` Albert Herranz
  0 siblings, 0 replies; 17+ messages in thread
From: Albert Herranz @ 2010-03-20  0:59 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk; +Cc: iommu, linux-usb, linuxppc-dev

Konrad Rzeszutek Wilk wrote:
>> +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);
> 
> Can you make them EXPORT_SYMBOL_GPL?

Sure. I don't know why I didn't use the *_GPL flavour on first place.

Thanks,
Albert

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

end of thread, other threads:[~2010-03-20  0:59 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-19 18:32 [PATCH v5 00/10] wii: add usb 2.0 support Albert Herranz
2010-03-19 18:32 ` [PATCH v5 01/10] swiotbl: add back swiotlb_alloc_boot() Albert Herranz
2010-03-19 18:32 ` [PATCH v5 02/10] swiotlb: make swiotlb_bounce() __weak Albert Herranz
2010-03-19 18:32 ` [PATCH v5 03/10] powerpc: add per-device dma coherent support Albert Herranz
2010-03-19 18:32 ` [PATCH v5 04/10] powerpc: add min_direct_dma_addr Albert Herranz
2010-03-19 18:32 ` [PATCH v5 05/10] USB: refactor unmap_urb_for_dma/map_urb_for_dma Albert Herranz
2010-03-19 18:32 ` [PATCH v5 06/10] USB: add HCD_NO_COHERENT_MEM host controller driver flag Albert Herranz
2010-03-19 18:32 ` [PATCH v5 07/10] wii: have generic dma coherent Albert Herranz
2010-03-19 18:32 ` [PATCH v5 08/10] wii: add mem2 dma mapping ops Albert Herranz
2010-03-19 19:50   ` Konrad Rzeszutek Wilk
2010-03-20  0:59     ` Albert Herranz
2010-03-19 19:51   ` Konrad Rzeszutek Wilk
2010-03-20  0:58     ` Albert Herranz
2010-03-19 18:32 ` [PATCH v5 09/10] wii: enable swiotlb Albert Herranz
2010-03-19 18:32 ` [PATCH v5 10/10] wii: hollywood ehci controller support Albert Herranz
2010-03-19 19:01 ` [PATCH v5 00/10] wii: add usb 2.0 support Alan Stern
2010-03-19 19:13   ` 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.