* [PATCH] [RFC] Xilinx Virtex 4 FX Soft FPU support
From: Sergey Temerkhanov @ 2010-03-19 15:47 UTC (permalink / raw)
To: linuxppc-dev
This patch enables support for Xilinx Virtex 4 FX singe-float FPU.
Caveats:
- Hard-float binaries which rely on in-kernel math emulation will give wrong
results since they expect 64-bit double-precision instead of 32-bit single-
precision numbers.
Regards, Sergey Temerkhanov
^ permalink raw reply
* Re: [PATCH] [RFC] Xilinx Virtex 4 FX Soft FPU support
From: Sergey Temerkhanov @ 2010-03-19 15:49 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <201003191847.55823.temerkhanov@cifronik.ru>
[-- Attachment #1: Type: Text/Plain, Size: 40 bytes --]
The patch.
Regards, Resgey Temerkhanov
[-- Attachment #2: fp.patch --]
[-- Type: text/x-patch, Size: 5213 bytes --]
diff -r 9d9ac97e095d .config
--- a/.config Thu Feb 25 21:23:42 2010 +0300
+++ b/.config Thu Feb 25 21:49:02 2010 +0300
@@ -14,10 +14,12 @@
CONFIG_40x=y
# CONFIG_44x is not set
# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
CONFIG_4xx=y
CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_XILINX_FPU=y
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -227,7 +229,7 @@
CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
-CONFIG_MATH_EMULATION=y
+# CONFIG_MATH_EMULATION is not set
# CONFIG_IOMMU_HELPER is not set
# CONFIG_SWIOTLB is not set
CONFIG_PPC_NEED_DMA_SYNC_OPS=y
diff -r 9d9ac97e095d arch/powerpc/include/asm/ppc_asm.h
--- a/arch/powerpc/include/asm/ppc_asm.h Thu Feb 25 21:23:42 2010 +0300
+++ b/arch/powerpc/include/asm/ppc_asm.h Thu Feb 25 21:49:02 2010 +0300
@@ -85,13 +85,23 @@
#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
-#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
+
+#ifdef CONFIG_XILINX_FPU
+#define stfr stfs
+#define lfr lfs
+#else
+#define stfr stfd
+#define lfr lfd
+#endif
+
+
+#define SAVE_FPR(n, base) stfr n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base)
#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base)
#define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base)
#define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base)
#define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base)
-#define REST_FPR(n, base) lfd n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
+#define REST_FPR(n, base) lfr n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
#define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base)
#define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, base)
#define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base)
diff -r 9d9ac97e095d arch/powerpc/kernel/fpu.S
--- a/arch/powerpc/kernel/fpu.S Thu Feb 25 21:23:42 2010 +0300
+++ b/arch/powerpc/kernel/fpu.S Thu Feb 25 21:49:02 2010 +0300
@@ -57,6 +57,9 @@
_GLOBAL(load_up_fpu)
mfmsr r5
ori r5,r5,MSR_FP
+#ifdef CONFIG_XILINX_FPU
+ oris r5,r5,MSR_VEC@h
+#endif
#ifdef CONFIG_VSX
BEGIN_FTR_SECTION
oris r5,r5,MSR_VSX@h
@@ -85,6 +88,9 @@
toreal(r5)
PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
li r10,MSR_FP|MSR_FE0|MSR_FE1
+#ifdef CONFIG_XILINX_FPU
+ oris r10,r10,MSR_VEC@h
+#endif
andc r4,r4,r10 /* disable FP for previous task */
PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1:
@@ -94,6 +100,9 @@
mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */
lwz r4,THREAD_FPEXC_MODE(r5)
ori r9,r9,MSR_FP /* enable FP for current */
+#ifdef CONFIG_XILINX_FPU
+ oris r9,r9,MSR_VEC@h
+#endif
or r9,r9,r4
#else
ld r4,PACACURRENT(r13)
@@ -124,6 +133,9 @@
_GLOBAL(giveup_fpu)
mfmsr r5
ori r5,r5,MSR_FP
+#ifdef CONFIG_XILINX_FPU
+ oris r5,r5,MSR_VEC@h
+#endif
#ifdef CONFIG_VSX
BEGIN_FTR_SECTION
oris r5,r5,MSR_VSX@h
@@ -145,6 +157,9 @@
beq 1f
PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
li r3,MSR_FP|MSR_FE0|MSR_FE1
+#ifdef CONFIG_XILINX_FPU
+ oris r3,r3,MSR_VEC@h
+#endif
#ifdef CONFIG_VSX
BEGIN_FTR_SECTION
oris r3,r3,MSR_VSX@h
diff -r 9d9ac97e095d arch/powerpc/kernel/head_40x.S
--- a/arch/powerpc/kernel/head_40x.S Thu Feb 25 21:23:42 2010 +0300
+++ b/arch/powerpc/kernel/head_40x.S Thu Feb 25 21:49:02 2010 +0300
@@ -420,7 +420,19 @@
addi r3,r1,STACK_FRAME_OVERHEAD
EXC_XFER_STD(0x700, program_check_exception)
+/* 0x0800 - FPU unavailable Exception */
+#ifdef CONFIG_PPC_FPU
+ START_EXCEPTION(0x0800, FloatingPointUnavailable)
+ NORMAL_EXCEPTION_PROLOG
+ beq 1f; \
+ bl load_up_fpu; /* if from user, just load it up */ \
+ b fast_exception_return; \
+1: addi r3,r1,STACK_FRAME_OVERHEAD; \
+ EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception)
+#else
EXCEPTION(0x0800, Trap_08, unknown_exception, EXC_XFER_EE)
+#endif
+
EXCEPTION(0x0900, Trap_09, unknown_exception, EXC_XFER_EE)
EXCEPTION(0x0A00, Trap_0A, unknown_exception, EXC_XFER_EE)
EXCEPTION(0x0B00, Trap_0B, unknown_exception, EXC_XFER_EE)
@@ -432,7 +444,7 @@
EXCEPTION(0x0D00, Trap_0D, unknown_exception, EXC_XFER_EE)
EXCEPTION(0x0E00, Trap_0E, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x0F00, Trap_0F, unknown_exception, EXC_XFER_EE)
+ EXCEPTION(0x0F20, Trap_0F, unknown_exception, EXC_XFER_EE)
/* 0x1000 - Programmable Interval Timer (PIT) Exception */
START_EXCEPTION(0x1000, Decrementer)
@@ -821,8 +833,10 @@
* The PowerPC 4xx family of processors do not have an FPU, so this just
* returns.
*/
+#ifndef CONFIG_PPC_FPU
_ENTRY(giveup_fpu)
blr
+#endif
/* This is where the main kernel code starts.
*/
diff -r 9d9ac97e095d arch/powerpc/platforms/Kconfig.cputype
--- a/arch/powerpc/platforms/Kconfig.cputype Thu Feb 25 21:23:42 2010 +0300
+++ b/arch/powerpc/platforms/Kconfig.cputype Thu Feb 25 21:49:02 2010 +0300
@@ -290,4 +290,9 @@
config CHECK_CACHE_COHERENCY
bool
+config XILINX_FPU
+ bool "Xilinx softFPU"
+ select PPC_FPU
+ depends on 40x
+
endmenu
^ permalink raw reply
* [PATCH v5 01/10] swiotbl: add back swiotlb_alloc_boot()
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk
In-Reply-To: <1269023546-25534-1-git-send-email-albert_herranz@yahoo.es>
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
* [PATCH v5 02/10] swiotlb: make swiotlb_bounce() __weak
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk
In-Reply-To: <1269023546-25534-1-git-send-email-albert_herranz@yahoo.es>
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
* [PATCH v5 04/10] powerpc: add min_direct_dma_addr
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk
In-Reply-To: <1269023546-25534-1-git-send-email-albert_herranz@yahoo.es>
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
* [PATCH v5 05/10] USB: refactor unmap_urb_for_dma/map_urb_for_dma
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk
In-Reply-To: <1269023546-25534-1-git-send-email-albert_herranz@yahoo.es>
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
* [PATCH v5 06/10] USB: add HCD_NO_COHERENT_MEM host controller driver flag
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk
In-Reply-To: <1269023546-25534-1-git-send-email-albert_herranz@yahoo.es>
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
* [PATCH v5 03/10] powerpc: add per-device dma coherent support
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk
In-Reply-To: <1269023546-25534-1-git-send-email-albert_herranz@yahoo.es>
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
* [PATCH v5 07/10] wii: have generic dma coherent
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk
In-Reply-To: <1269023546-25534-1-git-send-email-albert_herranz@yahoo.es>
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
* [PATCH v5 00/10] wii: add usb 2.0 support
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
* [PATCH v5 08/10] wii: add mem2 dma mapping ops
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk
In-Reply-To: <1269023546-25534-1-git-send-email-albert_herranz@yahoo.es>
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
* [PATCH v5 09/10] wii: enable swiotlb
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk
In-Reply-To: <1269023546-25534-1-git-send-email-albert_herranz@yahoo.es>
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
* [PATCH v5 10/10] wii: hollywood ehci controller support
From: Albert Herranz @ 2010-03-19 18:32 UTC (permalink / raw)
To: linux-usb, linuxppc-dev, iommu; +Cc: Albert Herranz, konrad.wilk
In-Reply-To: <1269023546-25534-1-git-send-email-albert_herranz@yahoo.es>
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
* Re: [PATCH v5 00/10] wii: add usb 2.0 support
From: Alan Stern @ 2010-03-19 19:01 UTC (permalink / raw)
To: Albert Herranz; +Cc: iommu, linux-usb, linuxppc-dev, konrad.wilk
In-Reply-To: <1269023546-25534-1-git-send-email-albert_herranz@yahoo.es>
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
* Re: [PATCH 1/2] irq: move some interrupt arch_* functions into struct irq_chip.
From: Yinghai Lu @ 2010-03-19 19:02 UTC (permalink / raw)
To: Ian Campbell
Cc: lguest, Jeremy Fitzhardinge, Rusty Russell, Paul Mundt, linux-sh,
x86, linux-kernel, linuxppc-dev, Ingo Molnar, Paul Mackerras,
Eric W. Biederman, H. Peter Anvin, Thomas Gleixner
In-Reply-To: <1268998041-22707-1-git-send-email-ian.campbell@citrix.com>
please check
Subject: [PATCH -v4] irq: move some interrupt arch_* functions into struct irq_chip.
From: Ian Campbell <ian.campbell@citrix.com>
Move arch_init_copy_chip_data and arch_free_chip_data into function
pointers in struct irq_chip since they operate on irq_desc->chip_data.
arch_init_chip_data cannot be moved into struct irq_chip because
irq_desc->chip is not known at the time the irq_desc is setup. Instead
rename arch_init_chip_data to arch_init_irq_desc for PowerPC, the
only other user, whose usage better matches the new name.
To replace the x86 arch_init_chip_data functionality
irq_to_desc_alloc_node now takes a pointer to a function to allocate
the chip data. This is necessary to ensure the allocation happens
under the correct locking at the core level. On PowerPC and SH
architectures (the other users of irq_to_desc_alloc_node) pass in NULL
which retains existing chip_data behaviour.
I've retained the chip_data behaviour for uv_irq although it isn't
clear to me if these interrupt types support migration or how closely
related to the APIC modes they really are. If it weren't for this the
x86_{init,copy,free}_chip_data functions could be static to
io_apic.c.
I've tested by booting on an 64 bit x86 system with sparse IRQ enabled
and 32 bit without, but it's not clear to me what actions I need to
take to actually exercise some of these code paths.
-v4: yinghai add irq_to_desc_alloc_node_x...
so could leave default path not changed...
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Acked-by: Michael Ellerman <michael@ellerman.id.au> [PowerPC rename portion]
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: x86@kernel.org
Cc: linuxppc-dev@ozlabs.org
Cc: linux-kernel@vger.kernel.org
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: lguest@ozlabs.org
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: linux-sh@vger.kernel.org
---
arch/powerpc/kernel/irq.c | 2 -
arch/x86/include/asm/hw_irq.h | 7 +++++
arch/x86/kernel/apic/io_apic.c | 49 +++++++++++++++++++++++++++++++++++++----
arch/x86/kernel/uv_irq.c | 3 ++
drivers/xen/events.c | 7 +++++
include/linux/interrupt.h | 1
include/linux/irq.h | 20 ++++++++++++----
kernel/irq/chip.c | 7 +++++
kernel/irq/handle.c | 13 ++++++----
kernel/irq/numa_migrate.c | 12 ++++++++--
kernel/softirq.c | 5 ----
11 files changed, 101 insertions(+), 25 deletions(-)
Index: linux-2.6/arch/powerpc/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/irq.c
+++ linux-2.6/arch/powerpc/kernel/irq.c
@@ -1088,7 +1088,7 @@ int arch_early_irq_init(void)
return 0;
}
-int arch_init_chip_data(struct irq_desc *desc, int node)
+int arch_init_irq_desc(struct irq_desc *desc, int node, init_chip_data_fn fn)
{
desc->status |= IRQ_NOREQUEST;
return 0;
Index: linux-2.6/arch/x86/include/asm/hw_irq.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/hw_irq.h
+++ linux-2.6/arch/x86/include/asm/hw_irq.h
@@ -20,9 +20,9 @@
#include <linux/percpu.h>
#include <linux/profile.h>
#include <linux/smp.h>
+#include <linux/irq.h>
#include <asm/atomic.h>
-#include <asm/irq.h>
#include <asm/sections.h>
/* Interrupt handlers registered during init_IRQ */
@@ -61,6 +61,11 @@ extern void init_VISWS_APIC_irqs(void);
extern void setup_IO_APIC(void);
extern void disable_IO_APIC(void);
+extern void x86_copy_chip_data(struct irq_desc *old_desc,
+ struct irq_desc *desc, int node);
+extern void x86_free_chip_data(struct irq_desc *old_desc,
+ struct irq_desc *desc);
+
struct io_apic_irq_attr {
int ioapic;
int ioapic_pin;
Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/apic/io_apic.c
+++ linux-2.6/arch/x86/kernel/apic/io_apic.c
@@ -211,7 +211,7 @@ static struct irq_cfg *get_one_free_irq_
return cfg;
}
-int arch_init_chip_data(struct irq_desc *desc, int node)
+static int x86_init_chip_data(struct irq_desc *desc, int node)
{
struct irq_cfg *cfg;
@@ -287,8 +287,8 @@ static void free_irq_2_pin(struct irq_cf
old_cfg->irq_2_pin = NULL;
}
-void arch_init_copy_chip_data(struct irq_desc *old_desc,
- struct irq_desc *desc, int node)
+void x86_copy_chip_data(struct irq_desc *old_desc,
+ struct irq_desc *desc, int node)
{
struct irq_cfg *cfg;
struct irq_cfg *old_cfg;
@@ -312,7 +312,7 @@ static void free_irq_cfg(struct irq_cfg
kfree(old_cfg);
}
-void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
+void x86_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
{
struct irq_cfg *old_cfg, *cfg;
@@ -329,6 +329,14 @@ void arch_free_chip_data(struct irq_desc
}
}
/* end for move_irq_desc */
+int arch_init_irq_desc(struct irq_desc *desc, int node,
+ init_chip_data_fn init_chip_data)
+{
+ if (!init_chip_data)
+ return x86_init_chip_data(desc, node);
+
+ return init_chip_data(desc, node);
+}
#else
struct irq_cfg *irq_cfg(unsigned int irq)
@@ -336,6 +344,15 @@ struct irq_cfg *irq_cfg(unsigned int irq
return irq < nr_irqs ? irq_cfgx + irq : NULL;
}
+void x86_copy_chip_data(struct irq_desc *old_desc,
+ struct irq_desc *desc, int node)
+{
+}
+
+void x86_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
+{
+}
+
#endif
struct io_apic {
@@ -2747,6 +2764,9 @@ static struct irq_chip ioapic_chip __rea
.set_affinity = set_ioapic_affinity_irq,
#endif
.retrigger = ioapic_retrigger_irq,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
static struct irq_chip ir_ioapic_chip __read_mostly = {
@@ -2762,6 +2782,9 @@ static struct irq_chip ir_ioapic_chip __
#endif
#endif
.retrigger = ioapic_retrigger_irq,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
static inline void init_IO_APIC_traps(void)
@@ -3474,6 +3497,9 @@ static struct irq_chip msi_chip = {
.set_affinity = set_msi_irq_affinity,
#endif
.retrigger = ioapic_retrigger_irq,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
static struct irq_chip msi_ir_chip = {
@@ -3487,6 +3513,9 @@ static struct irq_chip msi_ir_chip = {
#endif
#endif
.retrigger = ioapic_retrigger_irq,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
/*
@@ -3646,6 +3675,9 @@ static struct irq_chip dmar_msi_type = {
.set_affinity = dmar_msi_set_affinity,
#endif
.retrigger = ioapic_retrigger_irq,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
int arch_setup_dmar_msi(unsigned int irq)
@@ -3703,6 +3735,9 @@ static struct irq_chip ir_hpet_msi_type
#endif
#endif
.retrigger = ioapic_retrigger_irq,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
static struct irq_chip hpet_msi_type = {
@@ -3714,6 +3749,9 @@ static struct irq_chip hpet_msi_type = {
.set_affinity = hpet_msi_set_affinity,
#endif
.retrigger = ioapic_retrigger_irq,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
@@ -3800,6 +3838,9 @@ static struct irq_chip ht_irq_chip = {
.set_affinity = set_ht_irq_affinity,
#endif
.retrigger = ioapic_retrigger_irq,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
Index: linux-2.6/arch/x86/kernel/uv_irq.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/uv_irq.c
+++ linux-2.6/arch/x86/kernel/uv_irq.c
@@ -55,6 +55,9 @@ struct irq_chip uv_irq_chip = {
.eoi = uv_ack_apic,
.end = uv_noop,
.set_affinity = uv_set_irq_affinity,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
/*
Index: linux-2.6/drivers/xen/events.c
===================================================================
--- linux-2.6.orig/drivers/xen/events.c
+++ linux-2.6/drivers/xen/events.c
@@ -329,6 +329,11 @@ static void unmask_evtchn(int port)
put_cpu();
}
+static int xen_init_chip_data(struct irq_desc *desc, int node)
+{
+ return 0;
+}
+
static int find_unbound_irq(void)
{
int irq;
@@ -341,7 +346,7 @@ static int find_unbound_irq(void)
if (irq == nr_irqs)
panic("No available IRQ to bind to: increase nr_irqs!\n");
- desc = irq_to_desc_alloc_node(irq, 0);
+ desc = irq_to_desc_alloc_node_x(irq, 0, xen_init_chip_data);
if (WARN_ON(desc == NULL))
return -1;
Index: linux-2.6/include/linux/interrupt.h
===================================================================
--- linux-2.6.orig/include/linux/interrupt.h
+++ linux-2.6/include/linux/interrupt.h
@@ -611,6 +611,5 @@ struct irq_desc;
extern int early_irq_init(void);
extern int arch_probe_nr_irqs(void);
extern int arch_early_irq_init(void);
-extern int arch_init_chip_data(struct irq_desc *desc, int node);
#endif
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -131,6 +131,12 @@ struct irq_chip {
void (*bus_lock)(unsigned int irq);
void (*bus_sync_unlock)(unsigned int irq);
+ /* for move_irq_desc */
+ void (*copy_chip_data)(struct irq_desc *old_desc,
+ struct irq_desc *desc, int node);
+ void (*free_chip_data)(struct irq_desc *old_desc,
+ struct irq_desc *desc);
+
/* Currently used only by UML, might disappear one day.*/
#ifdef CONFIG_IRQ_RELEASE_METHOD
void (*release)(unsigned int irq, void *dev_id);
@@ -208,10 +214,6 @@ struct irq_desc {
const char *name;
} ____cacheline_internodealigned_in_smp;
-extern void arch_init_copy_chip_data(struct irq_desc *old_desc,
- struct irq_desc *desc, int node);
-extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc);
-
#ifndef CONFIG_SPARSE_IRQ
extern struct irq_desc irq_desc[NR_IRQS];
#endif
@@ -225,7 +227,15 @@ static inline struct irq_desc *move_irq_
}
#endif
-extern struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node);
+typedef int (*init_chip_data_fn)(struct irq_desc *, int node);
+int arch_init_irq_desc(struct irq_desc *desc, int node, init_chip_data_fn fn);
+struct irq_desc *irq_to_desc_alloc_node_x(unsigned int irq, int node,
+ init_chip_data_fn fn);
+static inline struct irq_desc *irq_to_desc_alloc_node(unsigned int irq,
+ int node)
+{
+ return irq_to_desc_alloc_node_x(irq, node, NULL);
+}
/*
* Pick up the arch-dependent methods:
Index: linux-2.6/kernel/irq/handle.c
===================================================================
--- linux-2.6.orig/kernel/irq/handle.c
+++ linux-2.6/kernel/irq/handle.c
@@ -100,7 +100,8 @@ void __ref init_kstat_irqs(struct irq_de
}
}
-static void init_one_irq_desc(int irq, struct irq_desc *desc, int node)
+static void init_one_irq_desc(int irq, struct irq_desc *desc, int node,
+ init_chip_data_fn init_chip_data)
{
memcpy(desc, &irq_desc_init, sizeof(struct irq_desc));
@@ -120,7 +121,7 @@ static void init_one_irq_desc(int irq, s
BUG_ON(1);
}
init_desc_masks(desc);
- arch_init_chip_data(desc, node);
+ arch_init_irq_desc(desc, node, init_chip_data);
}
/*
@@ -198,7 +199,8 @@ int __init early_irq_init(void)
return arch_early_irq_init();
}
-struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node)
+struct irq_desc * __ref irq_to_desc_alloc_node_x(unsigned int irq, int node,
+ init_chip_data_fn init_chip_data)
{
struct irq_desc *desc;
unsigned long flags;
@@ -227,7 +229,7 @@ struct irq_desc * __ref irq_to_desc_allo
printk(KERN_ERR "can not alloc irq_desc\n");
BUG_ON(1);
}
- init_one_irq_desc(irq, desc, node);
+ init_one_irq_desc(irq, desc, node, init_chip_data);
set_irq_desc(irq, desc);
@@ -277,7 +279,8 @@ struct irq_desc *irq_to_desc(unsigned in
return (irq < NR_IRQS) ? irq_desc + irq : NULL;
}
-struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node)
+struct irq_desc *irq_to_desc_alloc_node_x(unsigned int irq, int node,
+ init_chip_data_fn init_chip_data)
{
return irq_to_desc(irq);
}
Index: linux-2.6/kernel/irq/numa_migrate.c
===================================================================
--- linux-2.6.orig/kernel/irq/numa_migrate.c
+++ linux-2.6/kernel/irq/numa_migrate.c
@@ -47,7 +47,8 @@ static bool init_copy_one_irq_desc(int i
lockdep_set_class(&desc->lock, &irq_desc_lock_class);
init_copy_kstat_irqs(old_desc, desc, node, nr_cpu_ids);
init_copy_desc_masks(old_desc, desc);
- arch_init_copy_chip_data(old_desc, desc, node);
+ if (desc->chip->copy_chip_data)
+ desc->chip->copy_chip_data(old_desc, desc, node);
return true;
}
@@ -55,7 +56,8 @@ static void free_one_irq_desc(struct irq
{
free_kstat_irqs(old_desc, desc);
free_desc_masks(old_desc, desc);
- arch_free_chip_data(old_desc, desc);
+ if (desc->chip->free_chip_data)
+ desc->chip->free_chip_data(old_desc, desc);
}
static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
@@ -107,9 +109,15 @@ out_unlock:
struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
{
+
/* those static or target node is -1, do not move them */
if (desc->irq < NR_IRQS_LEGACY || node == -1)
return desc;
+ /* IRQ chip does not support movement */
+ if (desc->chip_data &&
+ (desc->chip->copy_chip_data == NULL ||
+ desc->chip->free_chip_data == NULL))
+ return desc;
if (desc->node != node)
desc = __real_move_irq_desc(desc, node);
Index: linux-2.6/kernel/softirq.c
===================================================================
--- linux-2.6.orig/kernel/softirq.c
+++ linux-2.6/kernel/softirq.c
@@ -895,8 +895,3 @@ int __init __weak arch_early_irq_init(vo
{
return 0;
}
-
-int __weak arch_init_chip_data(struct irq_desc *desc, int node)
-{
- return 0;
-}
Index: linux-2.6/kernel/irq/chip.c
===================================================================
--- linux-2.6.orig/kernel/irq/chip.c
+++ linux-2.6/kernel/irq/chip.c
@@ -758,3 +758,10 @@ void __init set_irq_probe(unsigned int i
desc->status &= ~IRQ_NOPROBE;
raw_spin_unlock_irqrestore(&desc->lock, flags);
}
+
+int __weak arch_init_irq_desc(struct irq_desc *desc, int node,
+ init_chip_data_fn init_chip_data)
+{
+ return 0;
+}
+
^ permalink raw reply
* Re: [PATCH v5 00/10] wii: add usb 2.0 support
From: Albert Herranz @ 2010-03-19 19:13 UTC (permalink / raw)
To: Alan Stern; +Cc: iommu, linux-usb, linuxppc-dev, konrad.wilk
In-Reply-To: <Pine.LNX.4.44L0.1003191452310.18602-100000@netrider.rowland.org>
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
* [v2 PATCH] of/flattree: Fix unhandled OF_DT_NOP tag when unflattening the device tree
From: Grant Likely @ 2010-03-19 20:01 UTC (permalink / raw)
To: devicetree-discuss, benh, monstr, linuxppc-dev
From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
NOPs within the property section are skipped, but NOPs between
OF_DT_END_NODE and OF_DT_BEGIN_NODE were not. My firmware NOPs out
entire nodes depending on various environment parameters.
of_scan_flat_dt already handles NOP more generally.
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
v2 - adapted to new location of unflatten_dt_node().
Jason, please test against 2.6.34-rc1
drivers/of/fdt.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 406757a..dee4fb5 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -376,8 +376,11 @@ unsigned long __init unflatten_dt_node(unsigned long mem,
if (!np->type)
np->type = "<NULL>";
}
- while (tag == OF_DT_BEGIN_NODE) {
- mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize);
+ while (tag == OF_DT_BEGIN_NODE || tag == OF_DT_NOP) {
+ if (tag == OF_DT_NOP)
+ *p += 4;
+ else
+ mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize);
tag = be32_to_cpup((__be32 *)(*p));
}
if (tag != OF_DT_END_NODE) {
^ permalink raw reply related
* Re: [PATCH v5 08/10] wii: add mem2 dma mapping ops
From: Konrad Rzeszutek Wilk @ 2010-03-19 19:50 UTC (permalink / raw)
To: Albert Herranz; +Cc: iommu, linux-usb, linuxppc-dev
In-Reply-To: <1269023546-25534-9-git-send-email-albert_herranz@yahoo.es>
> +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
* Re: [PATCH v5 08/10] wii: add mem2 dma mapping ops
From: Konrad Rzeszutek Wilk @ 2010-03-19 19:51 UTC (permalink / raw)
To: Albert Herranz; +Cc: iommu, linux-usb, linuxppc-dev
In-Reply-To: <1269023546-25534-9-git-send-email-albert_herranz@yahoo.es>
> +/*
> + * 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
* Re: [v2 PATCH] of/flattree: Fix unhandled OF_DT_NOP tag when unflattening the device tree
From: David Gibson @ 2010-03-20 0:24 UTC (permalink / raw)
To: Grant Likely; +Cc: devicetree-discuss, linuxppc-dev, monstr
In-Reply-To: <20100319200049.5195.97171.stgit@angua>
On Fri, Mar 19, 2010 at 02:01:49PM -0600, Grant Likely wrote:
> From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
>
> NOPs within the property section are skipped, but NOPs between
> OF_DT_END_NODE and OF_DT_BEGIN_NODE were not. My firmware NOPs out
> entire nodes depending on various environment parameters.
>
> of_scan_flat_dt already handles NOP more generally.
Fwiw, there's a test program in the libfdt/dtc tree called "nopulate"
which will liberally spread NOPs through a device tree blob (one
between every other tag), which might be useful for testing this
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH v5 08/10] wii: add mem2 dma mapping ops
From: Albert Herranz @ 2010-03-20 0:58 UTC (permalink / raw)
To: Konrad Rzeszutek Wilk; +Cc: iommu, linux-usb, linuxppc-dev
In-Reply-To: <20100319195114.GD31908@phenom.dumpdata.com>
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
* Re: [PATCH v5 08/10] wii: add mem2 dma mapping ops
From: Albert Herranz @ 2010-03-20 0:59 UTC (permalink / raw)
To: Konrad Rzeszutek Wilk; +Cc: iommu, linux-usb, linuxppc-dev
In-Reply-To: <20100319195013.GC31908@phenom.dumpdata.com>
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
* hvc_console breakage
From: Anton Blanchard @ 2010-03-20 13:10 UTC (permalink / raw)
To: amit.shah, alan, rusty, gregkh; +Cc: linuxppc-dev
Hi,
I haven't tracked down why, but e74d098c66543d0731de62eb747ccd5b636a6f4c
(hvc_console: Fix race between hvc_close and hvc_remove) is causing my PowerPC
box to hang during boot, right when init starts.
Anton
^ permalink raw reply
* [PATCH 09/24] macintosh: fix dangling pointers
From: Wolfram Sang @ 2010-03-20 14:12 UTC (permalink / raw)
To: kernel-janitors; +Cc: linux-kernel, linuxppc-dev, linux-i2c, Colin Leroy
In-Reply-To: <1269094385-16114-1-git-send-email-w.sang@pengutronix.de>
Fix I2C-drivers which missed setting clientdata to NULL before freeing the
structure it points to. Also fix drivers which do this _after_ the structure
was freed already.
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Cc: Colin Leroy <colin@colino.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Found using coccinelle, then reviewed. Full patchset is available via
kernel-janitors, linux-i2c, and LKML.
---
drivers/macintosh/therm_adt746x.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index c42eeb4..16d82f1 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -182,6 +182,7 @@ remove_thermostat(struct i2c_client *client)
thermostat = NULL;
+ i2c_set_clientdata(client, NULL);
kfree(th);
return 0;
@@ -399,6 +400,7 @@ static int probe_thermostat(struct i2c_client *client,
rc = read_reg(th, CONFIG_REG);
if (rc < 0) {
dev_err(&client->dev, "Thermostat failed to read config!\n");
+ i2c_set_clientdata(client, NULL);
kfree(th);
return -ENODEV;
}
--
1.7.0
^ permalink raw reply related
* 2.6.34-rc2 fails to boot on powerpc
From: Sachin Sant @ 2010-03-20 16:35 UTC (permalink / raw)
To: Linux/PPC Development
[-- Attachment #1: Type: text/plain, Size: 926 bytes --]
2.6.34-rc2 fails to boot on number of PowerPC boxes. The boot
hangs with the following messages :
/sbin/fsck.ext3 (1) -- /] fsck.ext3 -a /dev/sda5
/dev/sda5: clean, 726435/3948544 files, 9655477/15773808 blocks
fsck succeeded. Mounting root device read-write.
Mounting root /dev/sda5
mount -o rw,acl,user_xattr -t ext3 /dev/sda5 /root
kjournald starting. Commit interval 5 seconds
EXT3-fs (sda5): using internal journal
EXT3-fs (sda5): mounted filesystem with writeback data mode
mount: can't find /root/proc in /etc/fstab or /etc/mtab
/sbin/smart_agetty: can not determine 'console' speed
This problem seem to have started with
2.6.34-rc1-git9 (352d4657b23fbd329efccc396000a549e0150907).
Haven't yet tried a git bisect. Boot log attached
Thanks
-Sachin
--
---------------------------------
Sachin Sant
IBM Linux Technology Center
India Systems and Technology Labs
Bangalore, India
---------------------------------
[-- Attachment #2: boot-log --]
[-- Type: text/plain, Size: 8106 bytes --]
Using 0081e5dd bytes for initrd buffer
Please wait, loading kernel...
Allocated 00f00000 bytes for kernel @ 00d00000
Elf64 kernel loaded...
Loading ramdisk...
ramdisk loaded 0081e5dd @ 034d0000
OF stdout device is: /vdevice/vty@30000000
Preparing to boot Linux version 2.6.34-rc1-git9-autotest (root@llm62) (gcc version 4.3.2 [gcc-4_3-branch revision 141291] (SUSE Linux) ) #1 SMP Sat Mar 20 07:30:22 IST 2010
Max number of cores passed to firmware: 0x0000000000000200
Calling ibm,client-architecture-support... done
command line: root=/dev/sda5 IDENT=1269051459
memory layout at init:
memory_limit : 0000000000000000 (16 MB aligned)
alloc_bottom : 0000000003cf0000
alloc_top : 0000000008000000
alloc_top_hi : 0000000008000000
rmo_top : 0000000008000000
ram_top : 0000000008000000
instantiating rtas at 0x00000000074e0000... done
boot cpu hw idx 0000000000000000
starting cpu hw idx 0000000000000002... done
copying OF device tree...
Building dt strings...
Building dt structure...
Device tree strings 0x0000000003d00000 -> 0x0000000003d015fa
Device tree struct 0x0000000003d10000 -> 0x0000000003d30000
Calling quiesce...
returning from prom_init
Phyp-dump disabled at boot time
Using pSeries machine description
Using 1TB segments
Found initrd at 0xc0000000034d0000:0xc000000003cee5dd
bootconsole [udbg0] enabled
Partition configured for 4 cpus.
CPU maps initialized for 2 threads per core
Starting Linux PPC64 #1 SMP Sat Mar 20 07:30:22 IST 2010
-----------------------------------------------------
ppc64_pft_size = 0x1a
physicalMemorySize = 0x100000000
htab_hash_mask = 0x7ffff
-----------------------------------------------------
Initializing cgroup subsys cpuset
Initializing cgroup subsys cpu
Linux version 2.6.34-rc1-git9-autotest (root@llm62) (gcc version 4.3.2 [gcc-4_3-branch revision 141291] (SUSE Linux) ) #1 SMP Sat Mar 20 07:30:22 IST 2010
[boot]0012 Setup Arch
EEH: No capable adapters found
PPC64 nvram contains 15360 bytes
Zone PFN ranges:
DMA 0x00000000 -> 0x00010000
Normal empty
Movable zone start PFN for each node
early_node_map[1] active PFN ranges
1: 0x00000000 -> 0x00010000
Could not find start_pfn for node 0
[boot]0015 Setup Done
PERCPU: Embedded 1 pages/cpu @c000000000e00000 s24744 r0 d40792 u262144
pcpu-alloc: s24744 r0 d40792 u262144 alloc=1*1048576
pcpu-alloc: [0] 0 1 2 3
Built 2 zonelists in Node order, mobility grouping on. Total pages: 65480
Policy zone: DMA
Kernel command line: root=/dev/sda5 IDENT=1269051459
PID hash table entries: 4096 (order: -1, 32768 bytes)
freeing bootmem node 1
Memory: 4143168k/4194304k available (9408k kernel code, 51136k reserved, 2624k data, 1430k bss, 512k init)
SLUB: Genslabs=18, HWalign=128, Order=0-3, MinObjects=0, CPUs=4, Nodes=256
Hierarchical RCU implementation.
RCU-based detection of stalled CPUs is enabled.
NR_IRQS:512 nr_irqs:512
[boot]0020 XICS Init
[boot]0021 XICS Done
clocksource: timebase mult[7d0000] shift[22] registered
Console: colour dummy device 80x25
console [hvc0] enabled, bootconsole disabled
console [hvc0] enabled, bootconsole disabled
allocated 2621440 bytes of page_cgroup
please try 'cgroup_disable=memory' option if you don't want memory cgroups
Security Framework initialized
SELinux: Disabled at boot.
Dentry cache hash table entries: 524288 (order: 6, 4194304 bytes)
Inode-cache hash table entries: 262144 (order: 5, 2097152 bytes)
Mount-cache hash table entries: 4096
Initializing cgroup subsys ns
Initializing cgroup subsys cpuacct
Initializing cgroup subsys memory
Initializing cgroup subsys devices
Initializing cgroup subsys freezer
Initializing cgroup subsys blkio
Processor 1 found.
Processor 2 found.
Processor 3 found.
Brought up 4 CPUs
NET: Registered protocol family 16
IBM eBus Device Driver
POWER6 performance monitor hardware support registered
PCI: Probing PCI hardware
bio: create slab <bio-0> at 0
vgaarb: loaded
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
Switching to clocksource timebase
NET: Registered protocol family 2
IP route cache hash table entries: 32768 (order: 2, 262144 bytes)
TCP established hash table entries: 131072 (order: 5, 2097152 bytes)
TCP bind hash table entries: 65536 (order: 5, 2097152 bytes)
TCP: Hash tables configured (established 131072 bind 65536)
TCP reno registered
UDP hash table entries: 2048 (order: 1, 196608 bytes)
UDP-Lite hash table entries: 2048 (order: 1, 196608 bytes)
NET: Registered protocol family 1
Unpacking initramfs...
Freeing initrd memory: 8313k freed
IOMMU table initialized, virtual merging enabled
audit: initializing netlink socket (disabled)
type=2000 audit(1269051512.190:1): initialized
Kprobe smoke test started
Kprobe smoke test passed successfully
rcu-torture:--- Start of test: nreaders=8 nfakewriters=4 stat_interval=0 verbose=0 test_no_idle_hz=0 shuffle_interval=3 stutter=5 irqreader=1 fqs_duration=0 fqs_holdoff=0 fqs_stutter=3
HugeTLB registered 16 MB page size, pre-allocated 0 pages
HugeTLB registered 16 GB page size, pre-allocated 0 pages
VFS: Disk quotas dquot_6.5.2
Dquot-cache hash table entries: 8192 (order 0, 65536 bytes)
Btrfs loaded
msgmni has been set to 8108
alg: No test for stdrng (krng)
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 254)
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
pci_hotplug: PCI Hot Plug PCI Core version: 0.5
rpaphp: RPA HOT Plug PCI Controller Driver version: 0.1
Generic RTC Driver v1.07
Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
pmac_zilog: 0.6 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)
Uniform Multi-Platform E-IDE driver
ide-gd driver 1.18
IBM eHEA ethernet device driver (Release EHEA_0102)
ehea: eth0: Jumbo frames are disabled
ehea: eth0 -> logical port id #2
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
mice: PS/2 mouse device common for all mice
EDAC MC: Ver: 2.1.0 Mar 20 2010
usbcore: registered new interface driver hiddev
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
TCP cubic registered
NET: Registered protocol family 15
registered taskstats version 1
Freeing unused kernel memory: 512k freed
doing fast boot
SCSI subsystem initialized
ibmvscsi 30000002: SRP_VERSION: 16.a
scsi0 : IBM POWER Virtual SCSI Adapter 1.5.8
ibmvscsi 30000002: partner initialization complete
ibmvscsi 30000002: host srp version: 16.a, host partition VIO (1), OS 3, max io 1048576
ibmvscsi 30000002: fast_fail not supported in server
ibmvscsi 30000002: Client reserve enabled
ibmvscsi 30000002: sent SRP login
ibmvscsi 30000002: SRP_LOGIN succeeded
scsi 0:0:1:0: Direct-Access AIX VDASD 0001 PQ: 0 ANSI: 3
Creating device nodes with udev
udevd version 128 started
sd 0:0:1:0: [sda] 167772160 512-byte logical blocks: (85.8 GB/80.0 GiB)
sd 0:0:1:0: [sda] Write Protect is off
sd 0:0:1:0: [sda] Cache data unavailable
sd 0:0:1:0: [sda] Assuming drive cache: write through
sd 0:0:1:0: [sda] Cache data unavailable
sd 0:0:1:0: [sda] Assuming drive cache: write through
sda: sda1 sda2 < sda5 > sda3 sda4
sd 0:0:1:0: [sda] Cache data unavailable
sd 0:0:1:0: [sda] Assuming drive cache: write through
sd 0:0:1:0: [sda] Attached SCSI disk
Boot logging started on /dev/hvc0(/dev/console) at Sat Mar 20 02:18:33 2010
resume device not found (ignoring)
Waiting for device /dev/sda5 to appear: ok
showconsole: Warning: the ioctl TIOCGDEV is not known by the kernel
fsck 1.41.9 (22-Aug-2009)
[/sbin/fsck.ext3 (1) -- /] fsck.ext3 -a /dev/sda5
/dev/sda5: clean, 726435/3948544 files, 9655477/15773808 blocks
fsck succeeded. Mounting root device read-write.
Mounting root /dev/sda5
mount -o rw,acl,user_xattr -t ext3 /dev/sda5 /root
kjournald starting. Commit interval 5 seconds
EXT3-fs (sda5): using internal journal
EXT3-fs (sda5): mounted filesystem with writeback data mode
mount: can't find /root/proc in /etc/fstab or /etc/mtab
/sbin/smart_agetty: can not determine 'console' speed
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox