* [PATCH 06/13] 8xx: Always pin kernel instruction TLB
From: Joakim Tjernlund @ 2011-01-10 21:37 UTC (permalink / raw)
To: Willy Tarreau, Scott Wood, linuxppc-dev
In-Reply-To: <1294695479-344-1-git-send-email-Joakim.Tjernlund@transmode.se>
Various kernel asm modifies SRR0/SRR1 just before executing
a rfi. If such code crosses a page boundary you risk a TLB miss
which will clobber SRR0/SRR1. Avoid this by always pinning
kernel instruction TLB space.
Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
---
arch/ppc/kernel/head_8xx.S | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index 9eb383b..d992c24 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -777,12 +777,13 @@ start_here:
*/
initial_mmu:
tlbia /* Invalidate all TLB entries */
-#ifdef CONFIG_PIN_TLB
+
+/* Always pin the first 8 MB ITLB to prevent ITLB
+ misses while mucking around with SRR0/SRR1 in asm
+*/
lis r8, MI_RSV4I@h
ori r8, r8, 0x1c00
-#else
- li r8, 0
-#endif
+
mtspr MI_CTR, r8 /* Set instruction MMU control */
#ifdef CONFIG_PIN_TLB
--
1.7.3.4
^ permalink raw reply related
* [PATCH 05/13] 8xx: Update TLB asm so it behaves as linux mm expects.
From: Joakim Tjernlund @ 2011-01-10 21:37 UTC (permalink / raw)
To: Willy Tarreau, Scott Wood, linuxppc-dev
In-Reply-To: <1294695479-344-1-git-send-email-Joakim.Tjernlund@transmode.se>
Update the TLB asm to make proper use of _PAGE_DIRTY and _PAGE_ACCESSED.
Get rid of _PAGE_HWWRITE too.
Pros:
- PRESENT is copied to ACCESSED, fixing accounting
- DIRTY is mapped to 0x100, the changed bit, and is set directly
when a page has been made dirty.
- Proper RO/RW mapping of user space.
- Free up 2 SW TLB bits in the linux pte(add back _PAGE_WRITETHRU ?)
- kernel RO/user NA support. Not sure this is really needed, would save
a few insn if not required.
Cons:
- A few more instructions in the DTLB Miss routine.
Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
---
arch/ppc/kernel/head_8xx.S | 53 ++++++++++++++++++++++++++-----------------
include/asm-ppc/pgtable.h | 15 +++++------
2 files changed, 39 insertions(+), 29 deletions(-)
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index 5269e5b..9eb383b 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -361,25 +361,27 @@ InstructionTLBMiss:
*/
tophys(r21,r21)
ori r21,r21,1 /* Set valid bit */
- beq- 2f /* If zero, don't try to find a pte */
DO_8xx_CPU6(0x2b80, r3)
mtspr MI_TWC, r21 /* Set segment attributes */
+ beq- 2f /* If zero, don't try to find a pte */
DO_8xx_CPU6(0x3b80, r3)
mtspr MD_TWC, r21 /* Load pte table base address */
mfspr r21, MD_TWC /* ....and get the pte address */
lwz r20, 0(r21) /* Get the pte */
- ori r20, r20, _PAGE_ACCESSED
- stw r20, 0(r21)
-
+#if 1
+ /* if !swap, you can delete this */
+ rlwimi r20, r20, 5, _PAGE_PRESENT<<5 /* Copy PRESENT to ACCESSED */
+ stw r20, 0(r21) /* Update pte */
+#endif
/* The Linux PTE won't go exactly into the MMU TLB.
- * Software indicator bits 21, 22 and 28 must be clear.
+ * Software indicator bits 21 and 28 must be clear.
* Software indicator bits 24, 25, 26, and 27 must be
* set. All other Linux PTE bits control the behavior
* of the MMU.
*/
2: li r21, 0x00f0
- rlwimi r20, r21, 0, 24, 28 /* Set 24-27, clear 28 */
+ rlwimi r20, r21, 0, 0x07f8 /* Set 24-27, clear 21-23,28 */
DO_8xx_CPU6(0x2d80, r3)
mtspr MI_RPN, r20 /* Update TLB entry */
@@ -436,12 +438,25 @@ DataStoreTLBMiss:
DO_8xx_CPU6(0x3b80, r3)
mtspr MD_TWC, r21
- mfspr r21, MD_TWC /* get the pte address again */
- ori r20, r20, _PAGE_ACCESSED
- stw r20, 0(r21)
+#if 1
+ /* if !swap, you can delete this */
+ mfspr r21, MD_TWC /* get the pte address */
+ rlwimi r20, r20, 5, _PAGE_PRESENT<<5 /* Copy PRESENT to ACCESSED */
+ stw r20, 0(r21) /* Update pte */
+#endif
+
+ /* Honour kernel RO, User NA */
+ /* 0x200 == Extended encoding, bit 22 */
+ /* r20 |= (r20 & _PAGE_USER) >> 2 */
+ rlwimi r20, r20, 32-2, 0x200
+ /* r21 = (r20 & _PAGE_RW) >> 1 */
+ rlwinm r21, r20, 32-1, 0x200
+ or r20, r21, r20
+ /* invert RW and 0x200 bits */
+ xori r20, r20, _PAGE_RW | 0x200
/* The Linux PTE won't go exactly into the MMU TLB.
- * Software indicator bits 21, 22 and 28 must be clear.
+ * Software indicator bits 22 and 28 must be clear.
* Software indicator bits 24, 25, 26, and 27 must be
* set. All other Linux PTE bits control the behavior
* of the MMU.
@@ -488,11 +503,12 @@ DataTLBError:
stw r20, 0(r0)
stw r21, 4(r0)
- /* First, make sure this was a store operation.
- */
mfspr r20, DSISR
- andis. r21, r20, 0x0200 /* If set, indicates store op */
- beq 2f
+ andis. r21, r20, 0x4800 /* !translation or protection */
+ bne- 2f
+ /* Only Change bit left now, do it here as it is faster
+ * than trapping to the C fault handler.
+ */
/* The EA of a data TLB miss is automatically stored in the MD_EPN
* register. The EA of a data TLB error is automatically stored in
@@ -542,17 +558,12 @@ DataTLBError:
mfspr r21, MD_TWC /* ....and get the pte address */
lwz r20, 0(r21) /* Get the pte */
- andi. r21, r20, _PAGE_RW /* Is it writeable? */
- beq 2f /* Bail out if not */
-
- /* Update 'changed', among others.
- */
ori r20, r20, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
- mfspr r21, MD_TWC /* Get pte address again */
stw r20, 0(r21) /* and update pte in table */
+ xori r20, r20, _PAGE_RW /* RW bit is inverted */
/* The Linux PTE won't go exactly into the MMU TLB.
- * Software indicator bits 21, 22 and 28 must be clear.
+ * Software indicator bits 22 and 28 must be clear.
* Software indicator bits 24, 25, 26, and 27 must be
* set. All other Linux PTE bits control the behavior
* of the MMU.
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index 71b2165..2ba37d3 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -298,21 +298,20 @@ extern unsigned long vmalloc_start;
#define _PAGE_NO_CACHE 0x0002 /* I: cache inhibit */
#define _PAGE_SHARED 0x0004 /* No ASID (context) compare */
-/* These five software bits must be masked out when the entry is loaded
- * into the TLB.
+/* These three software bits must be masked out when the entry is loaded
+ * into the TLB, 2 SW bits free.
*/
#define _PAGE_EXEC 0x0008 /* software: i-cache coherency required */
#define _PAGE_GUARDED 0x0010 /* software: guarded access */
-#define _PAGE_DIRTY 0x0020 /* software: page changed */
-#define _PAGE_RW 0x0040 /* software: user write access allowed */
-#define _PAGE_ACCESSED 0x0080 /* software: page referenced */
+#define _PAGE_ACCESSED 0x0020 /* software: page referenced */
/* Setting any bits in the nibble with the follow two controls will
* require a TLB exception handler change. It is assumed unused bits
- * are always zero.
+ * are always zero, encoding(bit 22).
*/
-#define _PAGE_HWWRITE 0x0100 /* h/w write enable: never set in Linux PTE */
-#define _PAGE_USER 0x0800 /* One of the PP bits, the other is USER&~RW */
+#define _PAGE_DIRTY 0x0100 /* Changed: page changed */
+#define _PAGE_RW 0x0400 /* PP lsb(bit 21), user write access allowed */
+#define _PAGE_USER 0x0800 /* PP msb(bit 20), user access allowed */
#define _PMD_PRESENT PAGE_MASK
#define _PMD_PAGE_MASK 0x000c
--
1.7.3.4
^ permalink raw reply related
* [PATCH 04/13] 8xx: Fix CONFIG_PIN_TLB
From: Joakim Tjernlund @ 2011-01-10 21:37 UTC (permalink / raw)
To: Willy Tarreau, Scott Wood, linuxppc-dev
In-Reply-To: <1294695479-344-1-git-send-email-Joakim.Tjernlund@transmode.se>
The wrong register was loaded into MD_RPN.
Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
---
arch/ppc/kernel/head_8xx.S | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index 57858ce..5269e5b 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -840,13 +840,13 @@ initial_mmu:
mtspr MD_TWC, r9
li r11, MI_BOOTINIT /* Create RPN for address 0 */
addis r11, r11, 0x0080 /* Add 8M */
- mtspr MD_RPN, r8
+ mtspr MD_RPN, r11
addis r8, r8, 0x0080 /* Add 8M */
mtspr MD_EPN, r8
mtspr MD_TWC, r9
addis r11, r11, 0x0080 /* Add 8M */
- mtspr MD_RPN, r8
+ mtspr MD_RPN, r11
#endif
/* Since the cache is enabled according to the information we
--
1.7.3.4
^ permalink raw reply related
* [PATCH 03/13] 8xx: invalidate non present TLBs
From: Joakim Tjernlund @ 2011-01-10 21:37 UTC (permalink / raw)
To: Willy Tarreau, Scott Wood, linuxppc-dev
In-Reply-To: <1294695479-344-1-git-send-email-Joakim.Tjernlund@transmode.se>
8xx sometimes need to load a invalid/non-present TLBs in
it DTLB asm handler.
These must be invalidated separaly as linux mm don't.
Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
---
arch/ppc/mm/fault.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
index 9d3ce2d..874005a 100644
--- a/arch/ppc/mm/fault.c
+++ b/arch/ppc/mm/fault.c
@@ -116,7 +116,13 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
else
is_write = error_code & 0x02000000;
#endif /* CONFIG_4xx || CONFIG_BOOKE */
-
+#if defined(CONFIG_8xx)
+ /* 8xx does no invalidate TLBs that are ~PRESENT,
+ * do it here.
+ */
+ if (error_code & 0x40000000)
+ _tlbie(address);
+#endif
#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
if (debugger_fault_handler && regs->trap == 0x300) {
debugger_fault_handler(regs);
--
1.7.3.4
^ permalink raw reply related
* [PATCH 02/13] 8xx: Tag DAR with 0x00f0 to catch buggy instructions.
From: Joakim Tjernlund @ 2011-01-10 21:37 UTC (permalink / raw)
To: Willy Tarreau, Scott Wood, linuxppc-dev
In-Reply-To: <1294695479-344-1-git-send-email-Joakim.Tjernlund@transmode.se>
dcbz, dcbf, dcbi, dcbst and icbi do not set DAR when they
cause a DTLB Error. Dectect this by tagging DAR with 0x00f0
at every exception exit that modifies DAR.
This also fixes MachineCheck to pass DAR and DSISR as well.
Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
---
arch/ppc/kernel/head_8xx.S | 18 +++++++++++++++++-
1 files changed, 17 insertions(+), 1 deletions(-)
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index ba05a57..57858ce 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -197,7 +197,17 @@ label: \
STD_EXCEPTION(0x100, Reset, UnknownException)
/* Machine check */
- STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+ . = 0x200
+MachineCheck:
+ EXCEPTION_PROLOG
+ mfspr r20,DSISR
+ stw r20,_DSISR(r21)
+ mfspr r20,DAR
+ stw r20,_DAR(r21)
+ li r20,0x00f0
+ mtspr DAR,r20 /* Tag DAR */
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ FINISH_EXCEPTION(MachineCheckException)
/* Data access exception.
* This is "never generated" by the MPC8xx. We jump to it for other
@@ -211,6 +221,8 @@ DataAccess:
mr r5,r20
mfspr r4,DAR
stw r4,_DAR(r21)
+ li r20,0x00f0
+ mtspr DAR,r20 /* Tag DAR */
addi r3,r1,STACK_FRAME_OVERHEAD
li r20,MSR_KERNEL
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
@@ -249,6 +261,8 @@ Alignment:
EXCEPTION_PROLOG
mfspr r4,DAR
stw r4,_DAR(r21)
+ li r20,0x00f0
+ mtspr DAR,r20 /* Tag DAR */
mfspr r5,DSISR
stw r5,_DSISR(r21)
addi r3,r1,STACK_FRAME_OVERHEAD
@@ -433,6 +447,7 @@ DataStoreTLBMiss:
* of the MMU.
*/
2: li r21, 0x00f0
+ mtspr DAR, r21 /* Tag DAR */
rlwimi r20, r21, 0, 24, 28 /* Set 24-27, clear 28 */
DO_8xx_CPU6(0x3d80, r3)
mtspr MD_RPN, r20 /* Update TLB entry */
@@ -543,6 +558,7 @@ DataTLBError:
* of the MMU.
*/
li r21, 0x00f0
+ mtspr DAR, r21 /* Tag DAR */
rlwimi r20, r21, 0, 24, 28 /* Set 24-27, clear 28 */
DO_8xx_CPU6(0x3d80, r3)
mtspr MD_RPN, r20 /* Update TLB entry */
--
1.7.3.4
^ permalink raw reply related
* [PATCH 01/13] 8xx: Use a macro to simpliy CPU6 errata code.
From: Joakim Tjernlund @ 2011-01-10 21:37 UTC (permalink / raw)
To: Willy Tarreau, Scott Wood, linuxppc-dev
In-Reply-To: <1294695479-344-1-git-send-email-Joakim.Tjernlund@transmode.se>
Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
---
arch/ppc/kernel/head_8xx.S | 84 +++++++++++--------------------------------
1 files changed, 22 insertions(+), 62 deletions(-)
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index f9a30f3..ba05a57 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -31,6 +31,15 @@
#include <asm/ppc_asm.h>
#include "ppc_defs.h"
+/* Macro to make the code more readable. */
+#ifdef CONFIG_8xx_CPU6
+ #define DO_8xx_CPU6(val, reg) \
+ li reg, val; \
+ stw reg, 12(r0); \
+ lwz reg, 12(r0);
+#else
+ #define DO_8xx_CPU6(val, reg)
+#endif
.text
.globl _stext
_stext:
@@ -310,20 +319,14 @@ SystemCall:
InstructionTLBMiss:
#ifdef CONFIG_8xx_CPU6
stw r3, 8(r0)
- li r3, 0x3f80
- stw r3, 12(r0)
- lwz r3, 12(r0)
#endif
+ DO_8xx_CPU6(0x3f80, r3)
mtspr M_TW, r20 /* Save a couple of working registers */
mfcr r20
stw r20, 0(r0)
stw r21, 4(r0)
mfspr r20, SRR0 /* Get effective address of fault */
-#ifdef CONFIG_8xx_CPU6
- li r3, 0x3780
- stw r3, 12(r0)
- lwz r3, 12(r0)
-#endif
+ DO_8xx_CPU6(0x3780, r3)
mtspr MD_EPN, r20 /* Have to use MD_EPN for walk, MI_EPN can't */
mfspr r20, M_TWB /* Get level 1 table entry address */
@@ -345,17 +348,9 @@ InstructionTLBMiss:
tophys(r21,r21)
ori r21,r21,1 /* Set valid bit */
beq- 2f /* If zero, don't try to find a pte */
-#ifdef CONFIG_8xx_CPU6
- li r3, 0x2b80
- stw r3, 12(r0)
- lwz r3, 12(r0)
-#endif
+ DO_8xx_CPU6(0x2b80, r3)
mtspr MI_TWC, r21 /* Set segment attributes */
-#ifdef CONFIG_8xx_CPU6
- li r3, 0x3b80
- stw r3, 12(r0)
- lwz r3, 12(r0)
-#endif
+ DO_8xx_CPU6(0x3b80, r3)
mtspr MD_TWC, r21 /* Load pte table base address */
mfspr r21, MD_TWC /* ....and get the pte address */
lwz r20, 0(r21) /* Get the pte */
@@ -371,12 +366,7 @@ InstructionTLBMiss:
*/
2: li r21, 0x00f0
rlwimi r20, r21, 0, 24, 28 /* Set 24-27, clear 28 */
-
-#ifdef CONFIG_8xx_CPU6
- li r3, 0x2d80
- stw r3, 12(r0)
- lwz r3, 12(r0)
-#endif
+ DO_8xx_CPU6(0x2d80, r3)
mtspr MI_RPN, r20 /* Update TLB entry */
mfspr r20, M_TW /* Restore registers */
@@ -392,10 +382,8 @@ InstructionTLBMiss:
DataStoreTLBMiss:
#ifdef CONFIG_8xx_CPU6
stw r3, 8(r0)
- li r3, 0x3f80
- stw r3, 12(r0)
- lwz r3, 12(r0)
#endif
+ DO_8xx_CPU6(0x3f80, r3)
mtspr M_TW, r20 /* Save a couple of working registers */
mfcr r20
stw r20, 0(r0)
@@ -419,11 +407,7 @@ DataStoreTLBMiss:
tophys(r21, r21)
ori r21, r21, 1 /* Set valid bit in physical L2 page */
beq- 2f /* If zero, don't try to find a pte */
-#ifdef CONFIG_8xx_CPU6
- li r3, 0x3b80
- stw r3, 12(r0)
- lwz r3, 12(r0)
-#endif
+ DO_8xx_CPU6(0x3b80, r3)
mtspr MD_TWC, r21 /* Load pte table base address */
mfspr r20, MD_TWC /* ....and get the pte address */
lwz r20, 0(r20) /* Get the pte */
@@ -435,11 +419,7 @@ DataStoreTLBMiss:
* above.
*/
rlwimi r21, r20, 0, 27, 27
-#ifdef CONFIG_8xx_CPU6
- li r3, 0x3b80
- stw r3, 12(r0)
- lwz r3, 12(r0)
-#endif
+ DO_8xx_CPU6(0x3b80, r3)
mtspr MD_TWC, r21
mfspr r21, MD_TWC /* get the pte address again */
@@ -454,12 +434,7 @@ DataStoreTLBMiss:
*/
2: li r21, 0x00f0
rlwimi r20, r21, 0, 24, 28 /* Set 24-27, clear 28 */
-
-#ifdef CONFIG_8xx_CPU6
- li r3, 0x3d80
- stw r3, 12(r0)
- lwz r3, 12(r0)
-#endif
+ DO_8xx_CPU6(0x3d80, r3)
mtspr MD_RPN, r20 /* Update TLB entry */
mfspr r20, M_TW /* Restore registers */
@@ -491,10 +466,8 @@ InstructionTLBError:
DataTLBError:
#ifdef CONFIG_8xx_CPU6
stw r3, 8(r0)
- li r3, 0x3f80
- stw r3, 12(r0)
- lwz r3, 12(r0)
#endif
+ DO_8xx_CPU6(0x3f80, r3)
mtspr M_TW, r20 /* Save a couple of working registers */
mfcr r20
stw r20, 0(r0)
@@ -527,11 +500,7 @@ DataTLBError:
ori r21, r21, MD_EVALID
mfspr r20, M_CASID
rlwimi r21, r20, 0, 28, 31
-#ifdef CONFIG_8xx_CPU6
- li r3, 0x3780
- stw r3, 12(r0)
- lwz r3, 12(r0)
-#endif
+ DO_8xx_CPU6(0x3780, r3)
mtspr MD_EPN, r21
mfspr r20, M_TWB /* Get level 1 table entry address */
@@ -553,11 +522,7 @@ DataTLBError:
*/
tophys(r21, r21)
ori r21, r21, 1 /* Set valid bit in physical L2 page */
-#ifdef CONFIG_8xx_CPU6
- li r3, 0x3b80
- stw r3, 12(r0)
- lwz r3, 12(r0)
-#endif
+ DO_8xx_CPU6(0x3b80, r3)
mtspr MD_TWC, r21 /* Load pte table base address */
mfspr r21, MD_TWC /* ....and get the pte address */
lwz r20, 0(r21) /* Get the pte */
@@ -579,12 +544,7 @@ DataTLBError:
*/
li r21, 0x00f0
rlwimi r20, r21, 0, 24, 28 /* Set 24-27, clear 28 */
-
-#ifdef CONFIG_8xx_CPU6
- li r3, 0x3d80
- stw r3, 12(r0)
- lwz r3, 12(r0)
-#endif
+ DO_8xx_CPU6(0x3d80, r3)
mtspr MD_RPN, r20 /* Update TLB entry */
mfspr r20, M_TW /* Restore registers */
--
1.7.3.4
^ permalink raw reply related
* [PATCH 00/13] powerpc: Backport 8xx TLB to 2.4
From: Joakim Tjernlund @ 2011-01-10 21:37 UTC (permalink / raw)
To: Willy Tarreau, Scott Wood, linuxppc-dev
This is a backport from 2.6 which I did to overcome 8xx CPU
bugs. 8xx does not update the DAR register when taking a TLB
error caused by dcbX and icbi insns which makes it very
tricky to use these insns. Also the dcbst wrongly sets the
the store bit when faulting into DTLB error.
A few more bugs very found during development.
I know 2.4 is in strict maintenance mode and 8xx is obsolete
but as it is still in use I wanted 8xx to age with grace.
Joakim Tjernlund (13):
8xx: Use a macro to simpliy CPU6 errata code.
8xx: Tag DAR with 0x00f0 to catch buggy instructions.
8xx: invalidate non present TLBs
8xx: Fix CONFIG_PIN_TLB
8xx: Update TLB asm so it behaves as linux mm expects.
8xx: Always pin kernel instruction TLB
8xx: Fixup DAR from buggy dcbX instructions.
8xx: CPU6 errata make DTLB error too big to fit.
8xx: Add missing Guarded setting in DTLB Error.
8xx: Restore _PAGE_WRITETHRU
8xx: start using dcbX instructions in various copy routines
8xx: Optimize ITLBMiss handler.
8xx: Optimize TLB Miss handlers
arch/ppc/kernel/head_8xx.S | 364 ++++++++++++++++++++++++++++++--------------
arch/ppc/kernel/misc.S | 18 ---
arch/ppc/lib/string.S | 17 --
arch/ppc/mm/fault.c | 8 +-
include/asm-ppc/pgtable.h | 16 +-
5 files changed, 266 insertions(+), 157 deletions(-)
--
1.7.3.4
^ permalink raw reply
* Re: [PATCH 0/4] De-couple sysfs memory directories from memory sections
From: Robin Holt @ 2011-01-10 19:11 UTC (permalink / raw)
To: Nathan Fontenot
Cc: Greg KH, linux-kernel, linux-mm, Robin Holt, linuxppc-dev,
KAMEZAWA Hiroyuki
In-Reply-To: <4D2B543A.3070609@austin.ibm.com>
> >> The root of this issue is in sysfs directory creation. Every time
> >> a directory is created a string compare is done against all sibling
> >> directories to ensure we do not create duplicates. The list of
> >> directory nodes in sysfs is kept as an unsorted list which results
> >> in this being an exponentially longer operation as the number of
> >> directories are created.
> >
> > Are you sure this is still an issue? I thought we solved this last
> > kernel or so with a simple patch?
>
> I'll go back and look at this again.
What I recall fixing is the symbolic linking from the node* to the
memory section. In that case, we cached the most recent mem section
and since they always were added sequentially, the cache saved a rescan.
Of course, I could be remembering something completely unrelated.
Robin
^ permalink raw reply
* Re: [PATCH 0/4] De-couple sysfs memory directories from memory sections
From: Nathan Fontenot @ 2011-01-10 18:47 UTC (permalink / raw)
To: Greg KH; +Cc: linux-mm, linuxppc-dev, linux-kernel, KAMEZAWA Hiroyuki,
Robin Holt
In-Reply-To: <20110110184416.GA18974@kroah.com>
On 01/10/2011 12:44 PM, Greg KH wrote:
> On Mon, Jan 10, 2011 at 12:08:56PM -0600, Nathan Fontenot wrote:
>> This is a re-send of the remaining patches that did not make it
>> into the last kernel release for de-coupling sysfs memory
>> directories from memory sections. The first three patches of the
>> previous set went in, and this is the remaining patches that
>> need to be applied.
>
> Well, it's a bit late right now, as we are merging stuff that is already
> in our trees, and we are busy with that, so this is likely to be ignored
> until after .38-rc1 is out.
>
> So, care to resend this after .38-rc1 is out so people can pay attention
> to it?
I was afraid of this. I didn't get a chance to get it out sooner but thought
I would send it out anyway.
>
>
>> The root of this issue is in sysfs directory creation. Every time
>> a directory is created a string compare is done against all sibling
>> directories to ensure we do not create duplicates. The list of
>> directory nodes in sysfs is kept as an unsorted list which results
>> in this being an exponentially longer operation as the number of
>> directories are created.
>
> Are you sure this is still an issue? I thought we solved this last
> kernel or so with a simple patch?
I'll go back and look at this again.
thanks,
-Nathan
^ permalink raw reply
* Re: [PATCH 0/4] De-couple sysfs memory directories from memory sections
From: Greg KH @ 2011-01-10 18:44 UTC (permalink / raw)
To: Nathan Fontenot
Cc: linux-mm, linuxppc-dev, linux-kernel, KAMEZAWA Hiroyuki,
Robin Holt
In-Reply-To: <4D2B4B38.80102@austin.ibm.com>
On Mon, Jan 10, 2011 at 12:08:56PM -0600, Nathan Fontenot wrote:
> This is a re-send of the remaining patches that did not make it
> into the last kernel release for de-coupling sysfs memory
> directories from memory sections. The first three patches of the
> previous set went in, and this is the remaining patches that
> need to be applied.
Well, it's a bit late right now, as we are merging stuff that is already
in our trees, and we are busy with that, so this is likely to be ignored
until after .38-rc1 is out.
So, care to resend this after .38-rc1 is out so people can pay attention
to it?
> The root of this issue is in sysfs directory creation. Every time
> a directory is created a string compare is done against all sibling
> directories to ensure we do not create duplicates. The list of
> directory nodes in sysfs is kept as an unsorted list which results
> in this being an exponentially longer operation as the number of
> directories are created.
Are you sure this is still an issue? I thought we solved this last
kernel or so with a simple patch?
thanks,
greg k-h
^ permalink raw reply
* [PATCH 4/4] Define memory_block_size_bytes for x86_64 with CONFIG_X86_UV defined
From: Nathan Fontenot @ 2011-01-10 18:16 UTC (permalink / raw)
To: Greg KH; +Cc: linux-mm, linuxppc-dev, linux-kernel, KAMEZAWA Hiroyuki,
Robin Holt
In-Reply-To: <4D2B4B38.80102@austin.ibm.com>
Define a version of memory_block_size_bytes for x86_64 when CONFIG_X86_UV is
set.
Signed-off-by: Robin Holt <holt@sgi.com>
Signed-off-by: Jack Steiner <steiner@sgi.com>
Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
---
arch/x86/mm/init_64.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
Index: linux-2.6/arch/x86/mm/init_64.c
===================================================================
--- linux-2.6.orig/arch/x86/mm/init_64.c 2011-01-05 10:08:13.000000000 -0600
+++ linux-2.6/arch/x86/mm/init_64.c 2011-01-05 10:17:51.000000000 -0600
@@ -51,6 +51,7 @@
#include <asm/numa.h>
#include <asm/cacheflush.h>
#include <asm/init.h>
+#include <asm/uv/uv.h>
static int __init parse_direct_gbpages_off(char *arg)
{
@@ -908,6 +909,19 @@ const char *arch_vma_name(struct vm_area
return NULL;
}
+#ifdef CONFIG_X86_UV
+#define MIN_MEMORY_BLOCK_SIZE (1 << SECTION_SIZE_BITS)
+
+unsigned long memory_block_size_bytes(void)
+{
+ if (is_uv_system()) {
+ printk(KERN_INFO "UV: memory block size 2GB\n");
+ return 2UL * 1024 * 1024 * 1024;
+ }
+ return MIN_MEMORY_BLOCK_SIZE;
+}
+#endif
+
#ifdef CONFIG_SPARSEMEM_VMEMMAP
/*
* Initialise the sparsemem vmemmap using huge-pages at the PMD level.
^ permalink raw reply
* [PATCH 3/4] Define memory_block_size_bytes for powerpc/pseries
From: Nathan Fontenot @ 2011-01-10 18:14 UTC (permalink / raw)
To: Greg KH; +Cc: linux-mm, linuxppc-dev, linux-kernel, KAMEZAWA Hiroyuki,
Robin Holt
In-Reply-To: <4D2B4B38.80102@austin.ibm.com>
Define a version of memory_block_size_bytes() for powerpc/pseries such that
a memory block spans an entire lmb.
Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
Reviewed-by: Robin Holt <holt@sgi.com>
---
arch/powerpc/platforms/pseries/hotplug-memory.c | 66 +++++++++++++++++++-----
1 file changed, 53 insertions(+), 13 deletions(-)
Index: linux-2.6/arch/powerpc/platforms/pseries/hotplug-memory.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/pseries/hotplug-memory.c 2011-01-05 10:08:14.000000000 -0600
+++ linux-2.6/arch/powerpc/platforms/pseries/hotplug-memory.c 2011-01-05 10:17:49.000000000 -0600
@@ -17,6 +17,54 @@
#include <asm/pSeries_reconfig.h>
#include <asm/sparsemem.h>
+static unsigned long get_memblock_size(void)
+{
+ struct device_node *np;
+ unsigned int memblock_size = 0;
+
+ np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
+ if (np) {
+ const unsigned long *size;
+
+ size = of_get_property(np, "ibm,lmb-size", NULL);
+ memblock_size = size ? *size : 0;
+
+ of_node_put(np);
+ } else {
+ unsigned int memzero_size = 0;
+ const unsigned int *regs;
+
+ np = of_find_node_by_path("/memory@0");
+ if (np) {
+ regs = of_get_property(np, "reg", NULL);
+ memzero_size = regs ? regs[3] : 0;
+ of_node_put(np);
+ }
+
+ if (memzero_size) {
+ /* We now know the size of memory@0, use this to find
+ * the first memoryblock and get its size.
+ */
+ char buf[64];
+
+ sprintf(buf, "/memory@%x", memzero_size);
+ np = of_find_node_by_path(buf);
+ if (np) {
+ regs = of_get_property(np, "reg", NULL);
+ memblock_size = regs ? regs[3] : 0;
+ of_node_put(np);
+ }
+ }
+ }
+
+ return memblock_size;
+}
+
+unsigned long memory_block_size_bytes(void)
+{
+ return get_memblock_size();
+}
+
static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size)
{
unsigned long start, start_pfn;
@@ -127,30 +175,22 @@ static int pseries_add_memory(struct dev
static int pseries_drconf_memory(unsigned long *base, unsigned int action)
{
- struct device_node *np;
- const unsigned long *lmb_size;
+ unsigned long memblock_size;
int rc;
- np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
- if (!np)
+ memblock_size = get_memblock_size();
+ if (!memblock_size)
return -EINVAL;
- lmb_size = of_get_property(np, "ibm,lmb-size", NULL);
- if (!lmb_size) {
- of_node_put(np);
- return -EINVAL;
- }
-
if (action == PSERIES_DRCONF_MEM_ADD) {
- rc = memblock_add(*base, *lmb_size);
+ rc = memblock_add(*base, memblock_size);
rc = (rc < 0) ? -EINVAL : 0;
} else if (action == PSERIES_DRCONF_MEM_REMOVE) {
- rc = pseries_remove_memblock(*base, *lmb_size);
+ rc = pseries_remove_memblock(*base, memblock_size);
} else {
rc = -EINVAL;
}
- of_node_put(np);
return rc;
}
^ permalink raw reply
* [PATCH 2/4] Update phys_index to [start|end]_section_nr
From: Nathan Fontenot @ 2011-01-10 18:13 UTC (permalink / raw)
To: Greg KH; +Cc: linux-mm, linuxppc-dev, linux-kernel, KAMEZAWA Hiroyuki,
Robin Holt
In-Reply-To: <4D2B4B38.80102@austin.ibm.com>
Update the 'phys_index' property of a the memory_block struct to be
called start_section_nr, and add a end_section_nr property. The
data tracked here is the same but the updated naming is more in line
with what is stored here, namely the first and last section number
that the memory block spans.
The names presented to userspace remain the same, phys_index for
start_section_nr and end_phys_index for end_section_nr, to avoid breaking
anything in userspace.
This also updates the node sysfs code to be aware of the new capability for
a memory block to contain multiple memory sections and be aware of the memory
block structure name changes (start_section_nr). This requires an additional
parameter to unregister_mem_sect_under_nodes so that we know which memory
section of the memory block to unregister.
Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
Reviewed-by: Robin Holt <holt@sgi.com>
Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
---
drivers/base/memory.c | 41 +++++++++++++++++++++++++++++++----------
drivers/base/node.c | 12 ++++++++----
include/linux/memory.h | 3 ++-
include/linux/node.h | 6 ++++--
4 files changed, 45 insertions(+), 17 deletions(-)
Index: linux-2.6/drivers/base/memory.c
===================================================================
--- linux-2.6.orig/drivers/base/memory.c 2011-01-05 10:17:37.000000000 -0600
+++ linux-2.6/drivers/base/memory.c 2011-01-05 10:17:46.000000000 -0600
@@ -97,7 +97,7 @@ int register_memory(struct memory_block
int error;
memory->sysdev.cls = &memory_sysdev_class;
- memory->sysdev.id = memory->phys_index / sections_per_block;
+ memory->sysdev.id = memory->start_section_nr / sections_per_block;
error = sysdev_register(&memory->sysdev);
return error;
@@ -138,12 +138,26 @@ static unsigned long get_memory_block_si
* uses.
*/
-static ssize_t show_mem_phys_index(struct sys_device *dev,
+static ssize_t show_mem_start_phys_index(struct sys_device *dev,
struct sysdev_attribute *attr, char *buf)
{
struct memory_block *mem =
container_of(dev, struct memory_block, sysdev);
- return sprintf(buf, "%08lx\n", mem->phys_index / sections_per_block);
+ unsigned long phys_index;
+
+ phys_index = mem->start_section_nr / sections_per_block;
+ return sprintf(buf, "%08lx\n", phys_index);
+}
+
+static ssize_t show_mem_end_phys_index(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
+{
+ struct memory_block *mem =
+ container_of(dev, struct memory_block, sysdev);
+ unsigned long phys_index;
+
+ phys_index = mem->end_section_nr / sections_per_block;
+ return sprintf(buf, "%08lx\n", phys_index);
}
/*
@@ -158,7 +172,7 @@ static ssize_t show_mem_removable(struct
container_of(dev, struct memory_block, sysdev);
for (i = 0; i < sections_per_block; i++) {
- pfn = section_nr_to_pfn(mem->phys_index + i);
+ pfn = section_nr_to_pfn(mem->start_section_nr + i);
ret &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
}
@@ -275,14 +289,15 @@ static int memory_block_change_state(str
mem->state = MEM_GOING_OFFLINE;
for (i = 0; i < sections_per_block; i++) {
- ret = memory_section_action(mem->phys_index + i, to_state);
+ ret = memory_section_action(mem->start_section_nr + i,
+ to_state);
if (ret)
break;
}
if (ret) {
for (i = 0; i < sections_per_block; i++)
- memory_section_action(mem->phys_index + i,
+ memory_section_action(mem->start_section_nr + i,
from_state_req);
mem->state = from_state_req;
@@ -330,7 +345,8 @@ static ssize_t show_phys_device(struct s
return sprintf(buf, "%d\n", mem->phys_device);
}
-static SYSDEV_ATTR(phys_index, 0444, show_mem_phys_index, NULL);
+static SYSDEV_ATTR(phys_index, 0444, show_mem_start_phys_index, NULL);
+static SYSDEV_ATTR(end_phys_index, 0444, show_mem_end_phys_index, NULL);
static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state);
static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL);
static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL);
@@ -522,17 +538,21 @@ static int init_memory_block(struct memo
return -ENOMEM;
scn_nr = __section_nr(section);
- mem->phys_index = base_memory_block_id(scn_nr) * sections_per_block;
+ mem->start_section_nr =
+ base_memory_block_id(scn_nr) * sections_per_block;
+ mem->end_section_nr = mem->start_section_nr + sections_per_block - 1;
mem->state = state;
mem->section_count++;
mutex_init(&mem->state_mutex);
- start_pfn = section_nr_to_pfn(mem->phys_index);
+ start_pfn = section_nr_to_pfn(mem->start_section_nr);
mem->phys_device = arch_get_memory_phys_device(start_pfn);
ret = register_memory(mem);
if (!ret)
ret = mem_create_simple_file(mem, phys_index);
if (!ret)
+ ret = mem_create_simple_file(mem, end_phys_index);
+ if (!ret)
ret = mem_create_simple_file(mem, state);
if (!ret)
ret = mem_create_simple_file(mem, phys_device);
@@ -575,11 +595,12 @@ int remove_memory_block(unsigned long no
mutex_lock(&mem_sysfs_mutex);
mem = find_memory_block(section);
+ unregister_mem_sect_under_nodes(mem, __section_nr(section));
mem->section_count--;
if (mem->section_count == 0) {
- unregister_mem_sect_under_nodes(mem);
mem_remove_simple_file(mem, phys_index);
+ mem_remove_simple_file(mem, end_phys_index);
mem_remove_simple_file(mem, state);
mem_remove_simple_file(mem, phys_device);
mem_remove_simple_file(mem, removable);
Index: linux-2.6/drivers/base/node.c
===================================================================
--- linux-2.6.orig/drivers/base/node.c 2011-01-05 10:08:15.000000000 -0600
+++ linux-2.6/drivers/base/node.c 2011-01-05 10:17:46.000000000 -0600
@@ -360,8 +360,10 @@ int register_mem_sect_under_node(struct
return -EFAULT;
if (!node_online(nid))
return 0;
- sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index);
- sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1;
+
+ sect_start_pfn = section_nr_to_pfn(mem_blk->start_section_nr);
+ sect_end_pfn = section_nr_to_pfn(mem_blk->end_section_nr);
+ sect_end_pfn += PAGES_PER_SECTION - 1;
for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {
int page_nid;
@@ -385,7 +387,8 @@ int register_mem_sect_under_node(struct
}
/* unregister memory section under all nodes that it spans */
-int unregister_mem_sect_under_nodes(struct memory_block *mem_blk)
+int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
+ unsigned long phys_index)
{
NODEMASK_ALLOC(nodemask_t, unlinked_nodes, GFP_KERNEL);
unsigned long pfn, sect_start_pfn, sect_end_pfn;
@@ -397,7 +400,8 @@ int unregister_mem_sect_under_nodes(stru
if (!unlinked_nodes)
return -ENOMEM;
nodes_clear(*unlinked_nodes);
- sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index);
+
+ sect_start_pfn = section_nr_to_pfn(phys_index);
sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1;
for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {
int nid;
Index: linux-2.6/include/linux/memory.h
===================================================================
--- linux-2.6.orig/include/linux/memory.h 2011-01-05 10:08:15.000000000 -0600
+++ linux-2.6/include/linux/memory.h 2011-01-05 10:17:46.000000000 -0600
@@ -21,7 +21,8 @@
#include <linux/mutex.h>
struct memory_block {
- unsigned long phys_index;
+ unsigned long start_section_nr;
+ unsigned long end_section_nr;
unsigned long state;
int section_count;
Index: linux-2.6/include/linux/node.h
===================================================================
--- linux-2.6.orig/include/linux/node.h 2011-01-05 10:08:15.000000000 -0600
+++ linux-2.6/include/linux/node.h 2011-01-05 10:17:46.000000000 -0600
@@ -39,7 +39,8 @@ extern int register_cpu_under_node(unsig
extern int unregister_cpu_under_node(unsigned int cpu, unsigned int nid);
extern int register_mem_sect_under_node(struct memory_block *mem_blk,
int nid);
-extern int unregister_mem_sect_under_nodes(struct memory_block *mem_blk);
+extern int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
+ unsigned long phys_index);
#ifdef CONFIG_HUGETLBFS
extern void register_hugetlbfs_with_node(node_registration_func_t doregister,
@@ -67,7 +68,8 @@ static inline int register_mem_sect_unde
{
return 0;
}
-static inline int unregister_mem_sect_under_nodes(struct memory_block *mem_blk)
+static inline int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
+ unsigned long phys_index)
{
return 0;
}
^ permalink raw reply
* [PATCH 1/4] allow memory blocks to span multiple memory sections
From: Nathan Fontenot @ 2011-01-10 18:11 UTC (permalink / raw)
To: Greg KH; +Cc: linux-mm, linuxppc-dev, linux-kernel, KAMEZAWA Hiroyuki,
Robin Holt
In-Reply-To: <4D2B4B38.80102@austin.ibm.com>
Update the memory sysfs code such that each sysfs memory directory is now
considered a memory block that can span multiple memory sections per
memory block. The default size of each memory block is SECTION_SIZE_BITS
to maintain the current behavior of having a single memory section per
memory block (i.e. one sysfs directory per memory section).
For architectures that want to have memory blocks span multiple
memory sections they need only define their own memory_block_size_bytes()
routine.
Update the memory hotplug documentation to reflect the new behaviors of
memory blocks reflected in sysfs.
Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
Reviewed-by: Robin Holt <holt@sgi.com>
Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
---
Documentation/memory-hotplug.txt | 47 +++++++----
drivers/base/memory.c | 155 +++++++++++++++++++++++++++------------
2 files changed, 139 insertions(+), 63 deletions(-)
Index: linux-2.6/Documentation/memory-hotplug.txt
===================================================================
--- linux-2.6.orig/Documentation/memory-hotplug.txt 2011-01-05 10:08:16.000000000 -0600
+++ linux-2.6/Documentation/memory-hotplug.txt 2011-01-05 10:17:37.000000000 -0600
@@ -126,36 +126,51 @@ config options.
--------------------------------
4 sysfs files for memory hotplug
--------------------------------
-All sections have their device information under /sys/devices/system/memory as
+All sections have their device information in sysfs. Each section is part of
+a memory block under /sys/devices/system/memory as
/sys/devices/system/memory/memoryXXX
-(XXX is section id.)
+(XXX is the section id.)
-Now, XXX is defined as start_address_of_section / section_size.
+Now, XXX is defined as (start_address_of_section / section_size) of the first
+section contained in the memory block. The files 'phys_index' and
+'end_phys_index' under each directory report the beginning and end section id's
+for the memory block covered by the sysfs directory. It is expected that all
+memory sections in this range are present and no memory holes exist in the
+range. Currently there is no way to determine if there is a memory hole, but
+the existence of one should not affect the hotplug capabilities of the memory
+block.
For example, assume 1GiB section size. A device for a memory starting at
0x100000000 is /sys/device/system/memory/memory4
(0x100000000 / 1Gib = 4)
This device covers address range [0x100000000 ... 0x140000000)
-Under each section, you can see 4 files.
+Under each section, you can see 4 or 5 files, the end_phys_index file being
+a recent addition and not present on older kernels.
-/sys/devices/system/memory/memoryXXX/phys_index
+/sys/devices/system/memory/memoryXXX/start_phys_index
+/sys/devices/system/memory/memoryXXX/end_phys_index
/sys/devices/system/memory/memoryXXX/phys_device
/sys/devices/system/memory/memoryXXX/state
/sys/devices/system/memory/memoryXXX/removable
-'phys_index' : read-only and contains section id, same as XXX.
-'state' : read-write
- at read: contains online/offline state of memory.
- at write: user can specify "online", "offline" command
-'phys_device': read-only: designed to show the name of physical memory device.
- This is not well implemented now.
-'removable' : read-only: contains an integer value indicating
- whether the memory section is removable or not
- removable. A value of 1 indicates that the memory
- section is removable and a value of 0 indicates that
- it is not removable.
+'phys_index' : read-only and contains section id of the first section
+ in the memory block, same as XXX.
+'end_phys_index' : read-only and contains section id of the last section
+ in the memory block.
+'state' : read-write
+ at read: contains online/offline state of memory.
+ at write: user can specify "online", "offline" command
+ which will be performed on al sections in the block.
+'phys_device' : read-only: designed to show the name of physical memory
+ device. This is not well implemented now.
+'removable' : read-only: contains an integer value indicating
+ whether the memory block is removable or not
+ removable. A value of 1 indicates that the memory
+ block is removable and a value of 0 indicates that
+ it is not removable. A memory block is removable only if
+ every section in the block is removable.
NOTE:
These directories/files appear after physical memory hotplug phase.
Index: linux-2.6/drivers/base/memory.c
===================================================================
--- linux-2.6.orig/drivers/base/memory.c 2011-01-05 10:08:16.000000000 -0600
+++ linux-2.6/drivers/base/memory.c 2011-01-05 10:17:37.000000000 -0600
@@ -30,6 +30,14 @@
static DEFINE_MUTEX(mem_sysfs_mutex);
#define MEMORY_CLASS_NAME "memory"
+#define MIN_MEMORY_BLOCK_SIZE (1 << SECTION_SIZE_BITS)
+
+static int sections_per_block;
+
+static inline int base_memory_block_id(int section_nr)
+{
+ return section_nr / sections_per_block;
+}
static struct sysdev_class memory_sysdev_class = {
.name = MEMORY_CLASS_NAME,
@@ -84,28 +92,47 @@ EXPORT_SYMBOL(unregister_memory_isolate_
* register_memory - Setup a sysfs device for a memory block
*/
static
-int register_memory(struct memory_block *memory, struct mem_section *section)
+int register_memory(struct memory_block *memory)
{
int error;
memory->sysdev.cls = &memory_sysdev_class;
- memory->sysdev.id = __section_nr(section);
+ memory->sysdev.id = memory->phys_index / sections_per_block;
error = sysdev_register(&memory->sysdev);
return error;
}
static void
-unregister_memory(struct memory_block *memory, struct mem_section *section)
+unregister_memory(struct memory_block *memory)
{
BUG_ON(memory->sysdev.cls != &memory_sysdev_class);
- BUG_ON(memory->sysdev.id != __section_nr(section));
/* drop the ref. we got in remove_memory_block() */
kobject_put(&memory->sysdev.kobj);
sysdev_unregister(&memory->sysdev);
}
+unsigned long __weak memory_block_size_bytes(void)
+{
+ return MIN_MEMORY_BLOCK_SIZE;
+}
+
+static unsigned long get_memory_block_size(void)
+{
+ unsigned long block_sz;
+
+ block_sz = memory_block_size_bytes();
+
+ /* Validate blk_sz is a power of 2 and not less than section size */
+ if ((block_sz & (block_sz - 1)) || (block_sz < MIN_MEMORY_BLOCK_SIZE)) {
+ WARN_ON(1);
+ block_sz = MIN_MEMORY_BLOCK_SIZE;
+ }
+
+ return block_sz;
+}
+
/*
* use this as the physical section index that this memsection
* uses.
@@ -116,7 +143,7 @@ static ssize_t show_mem_phys_index(struc
{
struct memory_block *mem =
container_of(dev, struct memory_block, sysdev);
- return sprintf(buf, "%08lx\n", mem->phys_index);
+ return sprintf(buf, "%08lx\n", mem->phys_index / sections_per_block);
}
/*
@@ -125,13 +152,16 @@ static ssize_t show_mem_phys_index(struc
static ssize_t show_mem_removable(struct sys_device *dev,
struct sysdev_attribute *attr, char *buf)
{
- unsigned long start_pfn;
- int ret;
+ unsigned long i, pfn;
+ int ret = 1;
struct memory_block *mem =
container_of(dev, struct memory_block, sysdev);
- start_pfn = section_nr_to_pfn(mem->phys_index);
- ret = is_mem_section_removable(start_pfn, PAGES_PER_SECTION);
+ for (i = 0; i < sections_per_block; i++) {
+ pfn = section_nr_to_pfn(mem->phys_index + i);
+ ret &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
+ }
+
return sprintf(buf, "%d\n", ret);
}
@@ -184,17 +214,14 @@ int memory_isolate_notify(unsigned long
* OK to have direct references to sparsemem variables in here.
*/
static int
-memory_block_action(struct memory_block *mem, unsigned long action)
+memory_section_action(unsigned long phys_index, unsigned long action)
{
int i;
- unsigned long psection;
unsigned long start_pfn, start_paddr;
struct page *first_page;
int ret;
- int old_state = mem->state;
- psection = mem->phys_index;
- first_page = pfn_to_page(psection << PFN_SECTION_SHIFT);
+ first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT);
/*
* The probe routines leave the pages reserved, just
@@ -207,8 +234,8 @@ memory_block_action(struct memory_block
continue;
printk(KERN_WARNING "section number %ld page number %d "
- "not reserved, was it already online? \n",
- psection, i);
+ "not reserved, was it already online?\n",
+ phys_index, i);
return -EBUSY;
}
}
@@ -219,18 +246,13 @@ memory_block_action(struct memory_block
ret = online_pages(start_pfn, PAGES_PER_SECTION);
break;
case MEM_OFFLINE:
- mem->state = MEM_GOING_OFFLINE;
start_paddr = page_to_pfn(first_page) << PAGE_SHIFT;
ret = remove_memory(start_paddr,
PAGES_PER_SECTION << PAGE_SHIFT);
- if (ret) {
- mem->state = old_state;
- break;
- }
break;
default:
- WARN(1, KERN_WARNING "%s(%p, %ld) unknown action: %ld\n",
- __func__, mem, action, action);
+ WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: "
+ "%ld\n", __func__, phys_index, action, action);
ret = -EINVAL;
}
@@ -240,7 +262,8 @@ memory_block_action(struct memory_block
static int memory_block_change_state(struct memory_block *mem,
unsigned long to_state, unsigned long from_state_req)
{
- int ret = 0;
+ int i, ret = 0;
+
mutex_lock(&mem->state_mutex);
if (mem->state != from_state_req) {
@@ -248,8 +271,22 @@ static int memory_block_change_state(str
goto out;
}
- ret = memory_block_action(mem, to_state);
- if (!ret)
+ if (to_state == MEM_OFFLINE)
+ mem->state = MEM_GOING_OFFLINE;
+
+ for (i = 0; i < sections_per_block; i++) {
+ ret = memory_section_action(mem->phys_index + i, to_state);
+ if (ret)
+ break;
+ }
+
+ if (ret) {
+ for (i = 0; i < sections_per_block; i++)
+ memory_section_action(mem->phys_index + i,
+ from_state_req);
+
+ mem->state = from_state_req;
+ } else
mem->state = to_state;
out:
@@ -262,20 +299,15 @@ store_mem_state(struct sys_device *dev,
struct sysdev_attribute *attr, const char *buf, size_t count)
{
struct memory_block *mem;
- unsigned int phys_section_nr;
int ret = -EINVAL;
mem = container_of(dev, struct memory_block, sysdev);
- phys_section_nr = mem->phys_index;
-
- if (!present_section_nr(phys_section_nr))
- goto out;
if (!strncmp(buf, "online", min((int)count, 6)))
ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
else if(!strncmp(buf, "offline", min((int)count, 7)))
ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
-out:
+
if (ret)
return ret;
return count;
@@ -315,7 +347,7 @@ static ssize_t
print_block_size(struct sysdev_class *class, struct sysdev_class_attribute *attr,
char *buf)
{
- return sprintf(buf, "%lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE);
+ return sprintf(buf, "%lx\n", get_memory_block_size());
}
static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
@@ -444,6 +476,7 @@ struct memory_block *find_memory_block_h
struct sys_device *sysdev;
struct memory_block *mem;
char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
+ int block_id = base_memory_block_id(__section_nr(section));
kobj = hint ? &hint->sysdev.kobj : NULL;
@@ -451,7 +484,7 @@ struct memory_block *find_memory_block_h
* This only works because we know that section == sysdev->id
* slightly redundant with sysdev_register()
*/
- sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section));
+ sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, block_id);
kobj = kset_find_obj_hinted(&memory_sysdev_class.kset, name, kobj);
if (!kobj)
@@ -476,26 +509,27 @@ struct memory_block *find_memory_block(s
return find_memory_block_hinted(section, NULL);
}
-static int add_memory_block(int nid, struct mem_section *section,
- unsigned long state, enum mem_add_context context)
+static int init_memory_block(struct memory_block **memory,
+ struct mem_section *section, unsigned long state)
{
- struct memory_block *mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+ struct memory_block *mem;
unsigned long start_pfn;
+ int scn_nr;
int ret = 0;
+ mem = kzalloc(sizeof(*mem), GFP_KERNEL);
if (!mem)
return -ENOMEM;
- mutex_lock(&mem_sysfs_mutex);
-
- mem->phys_index = __section_nr(section);
+ scn_nr = __section_nr(section);
+ mem->phys_index = base_memory_block_id(scn_nr) * sections_per_block;
mem->state = state;
mem->section_count++;
mutex_init(&mem->state_mutex);
start_pfn = section_nr_to_pfn(mem->phys_index);
mem->phys_device = arch_get_memory_phys_device(start_pfn);
- ret = register_memory(mem, section);
+ ret = register_memory(mem);
if (!ret)
ret = mem_create_simple_file(mem, phys_index);
if (!ret)
@@ -504,8 +538,29 @@ static int add_memory_block(int nid, str
ret = mem_create_simple_file(mem, phys_device);
if (!ret)
ret = mem_create_simple_file(mem, removable);
+
+ *memory = mem;
+ return ret;
+}
+
+static int add_memory_section(int nid, struct mem_section *section,
+ unsigned long state, enum mem_add_context context)
+{
+ struct memory_block *mem;
+ int ret = 0;
+
+ mutex_lock(&mem_sysfs_mutex);
+
+ mem = find_memory_block(section);
+ if (mem) {
+ mem->section_count++;
+ kobject_put(&mem->sysdev.kobj);
+ } else
+ ret = init_memory_block(&mem, section, state);
+
if (!ret) {
- if (context == HOTPLUG)
+ if (context == HOTPLUG &&
+ mem->section_count == sections_per_block)
ret = register_mem_sect_under_node(mem, nid);
}
@@ -528,8 +583,10 @@ int remove_memory_block(unsigned long no
mem_remove_simple_file(mem, state);
mem_remove_simple_file(mem, phys_device);
mem_remove_simple_file(mem, removable);
- unregister_memory(mem, section);
- }
+ unregister_memory(mem);
+ kfree(mem);
+ } else
+ kobject_put(&mem->sysdev.kobj);
mutex_unlock(&mem_sysfs_mutex);
return 0;
@@ -541,7 +598,7 @@ int remove_memory_block(unsigned long no
*/
int register_new_memory(int nid, struct mem_section *section)
{
- return add_memory_block(nid, section, MEM_OFFLINE, HOTPLUG);
+ return add_memory_section(nid, section, MEM_OFFLINE, HOTPLUG);
}
int unregister_memory_section(struct mem_section *section)
@@ -560,12 +617,16 @@ int __init memory_dev_init(void)
unsigned int i;
int ret;
int err;
+ unsigned long block_sz;
memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops;
ret = sysdev_class_register(&memory_sysdev_class);
if (ret)
goto out;
+ block_sz = get_memory_block_size();
+ sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
+
/*
* Create entries for memory sections that were found
* during boot and have been initialized
@@ -573,8 +634,8 @@ int __init memory_dev_init(void)
for (i = 0; i < NR_MEM_SECTIONS; i++) {
if (!present_section_nr(i))
continue;
- err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE,
- BOOT);
+ err = add_memory_section(0, __nr_to_section(i), MEM_ONLINE,
+ BOOT);
if (!ret)
ret = err;
}
^ permalink raw reply
* [PATCH 0/4] De-couple sysfs memory directories from memory sections
From: Nathan Fontenot @ 2011-01-10 18:08 UTC (permalink / raw)
To: Greg KH; +Cc: linux-mm, linuxppc-dev, linux-kernel, KAMEZAWA Hiroyuki,
Robin Holt
This is a re-send of the remaining patches that did not make it
into the last kernel release for de-coupling sysfs memory
directories from memory sections. The first three patches of the
previous set went in, and this is the remaining patches that
need to be applied.
The patches decouple the concept that a single memory
section corresponds to a single directory in
/sys/devices/system/memory/. On systems
with large amounts of memory (1+ TB) there are performance issues
related to creating the large number of sysfs directories. For
a powerpc machine with 1 TB of memory we are creating 63,000+
directories. This is resulting in boot times of around 45-50
minutes for systems with 1 TB of memory and 8 hours for systems
with 2 TB of memory. With this patch set applied I am now seeing
boot times of 5 minutes or less.
The root of this issue is in sysfs directory creation. Every time
a directory is created a string compare is done against all sibling
directories to ensure we do not create duplicates. The list of
directory nodes in sysfs is kept as an unsorted list which results
in this being an exponentially longer operation as the number of
directories are created.
The solution solved by this patch set is to allow a single
directory in sysfs to span multiple memory sections. This is
controlled by an optional architecturally defined function
memory_block_size_bytes(). The default definition of this
routine returns a memory block size equal to the memory section
size. This maintains the current layout of sysfs memory
directories as it appears to userspace to remain the same as it
is today.
For architectures that define their own version of this routine,
as is done for powerpc and x86 in this patchset, the view in userspace
would change such that each memoryXXX directory would span
multiple memory sections. The number of sections spanned would
depend on the value reported by memory_block_size_bytes.
-Nathan Fontenot
^ permalink raw reply
* Re: mpc880 linux-2.6.32 slow running processes
From: Joakim Tjernlund @ 2011-01-10 16:55 UTC (permalink / raw)
To: Rafael Beims; +Cc: michael, linuxppc-dev, scottwood, RFeany
In-Reply-To: <AANLkTi=cAswFh1cFCU=nomd6yg5Ux9jK0x9h9s7f2571@mail.gmail.com>
Rafael Beims <rbeims@gmail.com> wrote on 2011/01/10 17:35:38:
> >
> > Once you have tested it and it works, please send a patch to remove the 8xx workaround.
> > Make sure Scott is cc:ed
> >
> >
>
> I tested linux-2.6.33 on my ppc880 board today, and even without the
> slowdown.patch applied, the board runs processes with good
> performance.
> It really seems that the problem is solved from linux-2.6.33 on.
>
> I'm not sure what you mean by sending a patch to remove the
> workaround. The only thing that I did in the 2.6.32 version was to
> apply the slowdown.patch attached in the message from Michael.
>
> Could you clarify please?
Yes, this part in arch/powerpc/mm/pgtable.c:
#ifdef CONFIG_8xx
/* On 8xx, cache control instructions (particularly
* "dcbst" from flush_dcache_icache) fault as write
* operation if there is an unpopulated TLB entry
* for the address in question. To workaround that,
* we invalidate the TLB here, thus avoiding dcbst
* misbehaviour.
*/
/* 8xx doesn't care about PID, size or ind args */
_tlbil_va(addr, 0, 0, 0);
#endif /* CONFIG_8xx */
Should be removed in >= 2.6.33 kernels.
My 8xx TLB work fixes this problem more efficiently.
Jocke
^ permalink raw reply
* Re: mpc880 linux-2.6.32 slow running processes
From: Rafael Beims @ 2011-01-10 16:35 UTC (permalink / raw)
To: Joakim Tjernlund; +Cc: michael, linuxppc-dev, scottwood, RFeany
In-Reply-To: <OFBA8894F8.FF5AA75D-ONC1257812.00773DA9-C1257812.00776196@transmode.se>
>
> Once you have tested it and it works, please send a patch to remove the 8xx workaround.
> Make sure Scott is cc:ed
>
>
I tested linux-2.6.33 on my ppc880 board today, and even without the
slowdown.patch applied, the board runs processes with good
performance.
It really seems that the problem is solved from linux-2.6.33 on.
I'm not sure what you mean by sending a patch to remove the
workaround. The only thing that I did in the 2.6.32 version was to
apply the slowdown.patch attached in the message from Michael.
Could you clarify please?
Thanks for all the help so far,
Rafael
^ permalink raw reply
* Re: [PATCH] USB: Fix USB Kconfig dependency problem on 85xx/QoirQ platforms
From: Kumar Gala @ 2011-01-10 16:22 UTC (permalink / raw)
To: Xulei Lei-B33228; +Cc: Greg KH, linux-usb, linuxppc-dev
In-Reply-To: <1294654017-32568-1-git-send-email-B33228@freescale.com>
On Jan 10, 2011, at 4:06 AM, Xulei wrote:
> For FSL PPC SoCs USB_ARCH_HAS_EHCI currently on depends on PPC_83xx.
> However that excludes support for USB on 85xx & QorIQ devices. Use
> FSL_SOC insted which will get us 83xx, 85xx, QorIQ, and 5xxx which all
> have the same USB IP on them.
>
> Signed-off-by: Xulei <B33228@freescale.com>
> Signed-off-by: Kumar Gala <kumar.gala@freescale.com>
> ---
> drivers/usb/Kconfig | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
> index 6a58cb1..d513d3a 100644
> --- a/drivers/usb/Kconfig
> +++ b/drivers/usb/Kconfig
> @@ -57,7 +57,7 @@ config USB_ARCH_HAS_OHCI
> # some non-PCI hcds implement EHCI
> config USB_ARCH_HAS_EHCI
> boolean
> - default y if PPC_83xx
> + default y if FSL_SOC
> default y if SOC_AU1200
> default y if ARCH_IXP4XX
> default y if ARCH_W90X900
> --
> 1.7.0.4
This really should have been CC'd to the USB list & maintainer.
- k
^ permalink raw reply
* Re: PCI woes with 2.6.37
From: Gary Thomas @ 2011-01-10 14:01 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: Linux PPC Development
In-Reply-To: <4D28617A.8020606@mlbassoc.com>
On 01/08/2011 06:07 AM, Gary Thomas wrote:
> On 01/08/2011 12:33 AM, Benjamin Herrenschmidt wrote:
>> On Fri, 2011-01-07 at 16:06 -0700, Gary Thomas wrote:
>>> I just tried porting my target (MPC8347) from 2.6.28 (remember
>>> that one?) to 2.6.37. Recently I tried this with 2.6.32 without
>>> a lot of success, so I thought I'd try the latest :-) The changes
>>> are very simple, pretty much just the addition of my 8347 based
>>> platform DTS.
>>>
>>> Sadly, it fails even worse than it did on 2.6.32.
>>>
>>> For some reason, although everything seems to report that the
>>> PCI bus is alive, MEM access fails completely. If I try to
>>> access various PCI devices via their memory space (I only have
>>> memory peripherals so I can't test IO space access), I get
>>> what I assume are BUS timeouts - all 0xFFFFFFFF
>>>
>>> My PCI bus is defined in DTS like this:
>>
>>> ranges =<0x02000000 0x0 0xC0000000 0xC0000000 0x0 0x20000000
>>
>> What are the #address-cells and #size-cells properties of the parent of
>> the PCI controller node ?
>>
>> PCI has 3 cells, so that accounts for the first 3 numbers of each of
>> these. That leaves only 3 numbers, so either you have #address-cells = 1
>> and #size-cells = 2 or the other way around.
>>
>> The first sounds the most plausible and would mean that you are mapping
>> c0000000 CPU space to c0000000 PCI space and the window is 512M long.
>>
>> Now of course, one needs to double check that the HW is configured that
>> way (I suppose fsl_pci.c does the configuration based on the "ranges"
>> property but I don't know for sure).
>>
>> So far nothing strikes me as totally odd.
>>
>>> 0x01000000 0x0 0x00000000 0xB8000000 0x0 0x00100000>;
>>
>> This looks reasonable too with the same assumption as above.
>>
>>> PCI: Probing PCI hardware
>>> PCI: Scanning PHB /pci@ff008500
>>> PCI: PHB IO resource = 0000000000000000-00000000000FF FFf [100]
>>> PCI: PHB MEM resource 0 = 00000000c0000000-00000000dFF FFfff [200]
>>
>> Did you edit those by hand ? :-) They look correct tho as far as I can
>> tell.
>
> Sorry, I did a little editing of the dump below (to make it more readable,
> no content changes) and "find & replace" went wild on me :-( It should
> have read:
> PCI: PHB MEM resource 0 = 00000000c0000000-00000000dfffffff [200]
>
>>
>>
>>> PCI: PHB MEM offset = 0000000000000000
>>> PCI: PHB IO offset = 00000000
>>
>> And that too.
>>
>>> probe mode: 0
>>> PCI:0000:00:0b.0 Resource 0 0000000000001000-0000000000001007 [40101] fixup...
>>> PCI:0000:00:0b.0 0000000000001000-0000000000001007
>>> PCI:0000:00:0b.0 Resource 1 0000000000001008-000000000000100b [40101] fixup...
>>> PCI:0000:00:0b.0 0000000000001008-000000000000100b
>>> PCI:0000:00:0b.0 Resource 2 0000000000001010-0000000000001017 [40101] fixup...
>>> PCI:0000:00:0b.0 0000000000001010-0000000000001017
>>> PCI:0000:00:0b.0 Resource 3 0000000000001018-000000000000101b [40101] fixup...
>>> PCI:0000:00:0b.0 0000000000001018-000000000000101b
>>> PCI:0000:00:0b.0 Resource 4 0000000000001020-000000000000102f [40101] fixup...
>>> PCI:0000:00:0b.0 0000000000001020-000000000000102f
>>> PCI:0000:00:0b.0 Resource 5 0000000000100000-00000000001001ff [40200] fixup...
>>> PCI:0000:00:0b.0 0000000000100000-00000000001001ff
>>> PCI:0000:00:0b.0 Resource 6 0000000000000000-000000000007FF FF [4e200] is unassigned
>>> PCI:0000:00:0c.0 Resource 0 0000000004000000-0000000007FF FFff [40200] fixup...
>>> PCI:0000:00:0c.0 0000000004000000-0000000007FF FFff
>>> PCI: Fixup bus devices 0 (PHB)
>>> PCI: Try to map irq for 0000:00:0b.0...
>>> Got one, spec 2 cells (0x00000016 0x00000008...) on /soc8349@ff000000/pic@700
>>> Mapped to linux irq 22
>>> PCI: Try to map irq for 0000:00:0c.0...
>>> Got one, spec 2 cells (0x00000013 0x00000008...) on /soc8349@ff000000/pic@700
>>> Mapped to linux irq 19
>>> PCI: Allocating bus resources for 0000:00...
>>> PCI: PHB (bus 0) bridge rsrc 0: 0000000000000000-00000000000FF FFf [0x100], parent c03b5740 (PCI IO)
>>> PCI: PHB (bus 0) bridge rsrc 1: 00000000c0000000-00000000dFF FFfff [0x200], parent c03b5724 (PCI mem)
>>> PCI: Allocating 0000:00:0b.0: Resource 0: 0000000000001000..0000000000001007 [40101]
>>> PCI: Allocating 0000:00:0b.0: Resource 1: 0000000000001008..000000000000100b [40101]
>>> PCI: Allocating 0000:00:0b.0: Resource 2: 0000000000001010..0000000000001017 [40101]
>>> PCI: Allocating 0000:00:0b.0: Resource 3: 0000000000001018..000000000000101b [40101]
>>> PCI: Allocating 0000:00:0b.0: Resource 4: 0000000000001020..000000000000102f [40101]
>>> PCI: Allocating 0000:00:0b.0: Resource 5: 0000000000100000..00000000001001ff [40200]
>>> PCI: Cannot allocate resource region 5 of device 0000:00:0b.0, will remap
>>> PCI: Allocating 0000:00:0c.0: Resource 0: 0000000004000000..0000000007FF FFff [40200]
>>
>> That's huge, is this your "Coral" framebuffer ? It's clearly using a
>> different address scheme which won't fit, so the kernel decides to remap
>> it, so far so good.
>
> Indeed, the frame buffer takes 4MB
>
>>
>>> PCI: Cannot allocate resource region 0 of device 0000:00:0c.0, will remap
>>> Reserving legacy ranges for domain 0000
>>> Candidate legacy IO: [io 0x0000-0x0fff]
>>> hose mem offset: 0000000000000000
>>> hose mem res: [mem 0xc0000000-0xdFF FFfff]
>>> Local memory hole: [mem 0xc0000000-0xc01FF FFf]
>>
>> Now I can't grep the above string, what is it ? What is this "memory
>> hole" ? It covers a good part of your PCI mapping ...
>>
>>> PCI: Assigning unassigned resources...
>>> pci 0000:00:0c.0: BAR 0: assigned [mem 0xc4000000-0xc7FF FFff]
>>> pci 0000:00:0c.0: BAR 0: set to [mem 0xc4000000-0xc7FF FFff] (PCI address [0xc4000000-0xc7FF FFff])
>>
>> So you fb looks like it has now landed at c4000000, which doesn't strike
>> me as wrong nor strange so far...
>>
>>> pci 0000:00:0b.0: BAR 6: assigned [mem 0xc0200000-0xc027FF FF pref]
>>> pci 0000:00:0b.0: BAR 5: assigned [mem 0xc0280000-0xc02801ff]
>>> pci 0000:00:0b.0: BAR 5: set to [mem 0xc0280000-0xc02801ff] (PCI address [0xc0280000-0xc02801ff])
>>> ...
>>> Coral-P FB [1024x768x24] at 0xc4000000..0xc7FF FFff [0xd1100000]
>>
>> I suspect 0xd1100000 is the result of ioremap ?
>>
>>> D1100000: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |................|
>>> D1100010: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |................|
>>> D1100020: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |................|
>>> D1100030: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |................|
>>> D1100040: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |................|
>>> D1100050: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |................|
>>> D1100060: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |................|
>>> D1100070: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |................|
>>> ...
>>> scsi0 : sata_sil
>>> scsi1 : sata_sil
>>> ata1: SATA max UDMA/100 mmio m512@0xc0280000 tf 0xc0280080 irq 22
>>> ata2: SATA max UDMA/100 mmio m512@0xc0280000 tf 0xc02800c0 irq 22
>>> ata1: failed to resume link (SControl FFFFFFFF)
>>> ata1: SATA link down (SStatus FFFFFFFF SControl FFFFFFFF)
>>> ata2: failed to resume link (SControl FFFFFFFF)
>>> ata2: SATA link down (SStatus FFFFFFFF SControl FFFFFFFF)
>>>
>>> Things of note:
>>> * The 'local memory hole' is a space I have to steal from the PCI
>>> address space so that the Coral-P gets mapped to something other
>>> than PCI memory address 0x0 (relative). This device is dirt stupid
>>> (previously discussed) and refuses to work at 0x0
>>> * The dump after the Coral-P FB line is what it sees in it's memory
>>> space. It _should_ look something like this:
>>> C4140600: FF FF FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 |................|
>>> C4140610: FF FF FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 |................|
>>> C4140620: FF FF FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 |................|
>>> C4140630: FF FF FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 |................|
>>> C4140640: FF FF FF 00 FF FF FF 00 FF FD FF 00 FF FD FF 00 |................|
>>> C4140650: FF FD FF 00 FF FD FF 00 FF FD FF 00 FF FD FF 00 |................|
>>> Notice how byte 3 of every longword is 0x00?
>>> * The SATA device driver is failing along similar lines.
>>>
>>> Any ideas what I'm doing wrong? or what I can look at?
>>
>> I can't see anything obviously wrong in what you've pasted there, but I
>> am not familiar with fsl PCI or SoC's, so it's possible that there's
>> something there going on ... We'll have to wait for somebody from FSL to
>> have a look, unless you can find something in the doco.
>
> The curious thing is that this exact same setup works perfectly
> in 2.6.28 and near perfectly in 2.6.32. Unless something else
> changed in the PCI handling between 2.6.32 and 2.6.37, I would
> hope it work work there as well.
>
> I'll keep looking for differences between those two system versions.
I found the problem - a change I had in <2.6.32 that I hadn't
pushed forward. It seems to be related to how I have the PCI
controller setup (in RedBoot). Because of this, using these
settings in my DTS make things work properly:
ranges = <0x02000000 0x0 0x00000000 0xC0000000 0x0 0x20000000
0x01000000 0x0 0x00000000 0xB8000000 0x0 0x00100000>;
Instead of
ranges = <0x02000000 0x0 0xC0000000 0xC0000000 0x0 0x20000000
0x01000000 0x0 0x00000000 0xB8000000 0x0 0x00100000>;
Sorry for the noise (wild goose chase), but discussing it did help
me to work out some PCI issues in general.
Now that this is working, I'm trying to move to the next problem.
The system works fine, but only to a point. In this [embedded]
system, I have an SIL SATA controller on the PCI bus. On 2.6.28,
this device is rock solid. On 2.6.32 and now 2.6.37, I have issues.
Operations work on the device (connected to a SSD), but after some
arbitrary time, an operation will fail, causing the PCI bus (and
indeed the whole system) to hang. I've tried to peek in using a
BDI and once it hangs, even the BDI can't access the CPU any more.
I'm pretty lost on this one - it will execute hundreds of SATA operations
properly and then die. Turning on SATA/SCSI traces, I can see the
final operation be issued and there seems to be no substantive difference
between this operation and the previous ones that all worked. In fact
if I reset and rerun the same program, it _will_ fail but never on
the same operation :-(
Any ideas what could cause this failure? I have a similar system
that uses a different SATA controller that I'm going to try. Maybe
it's something peculiar to the SIL device as opposed to generic PCI
operations.
Thanks for any feedback
--
------------------------------------------------------------
Gary Thomas | Consulting for the
MLB Associates | Embedded world
------------------------------------------------------------
^ permalink raw reply
* [PATCH] USB: Fix USB Kconfig dependency problem on 85xx/QoirQ platforms
From: Xulei @ 2011-01-10 10:06 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Xulei, Kumar Gala
For FSL PPC SoCs USB_ARCH_HAS_EHCI currently on depends on PPC_83xx.
However that excludes support for USB on 85xx & QorIQ devices. Use
FSL_SOC insted which will get us 83xx, 85xx, QorIQ, and 5xxx which all
have the same USB IP on them.
Signed-off-by: Xulei <B33228@freescale.com>
Signed-off-by: Kumar Gala <kumar.gala@freescale.com>
---
drivers/usb/Kconfig | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 6a58cb1..d513d3a 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -57,7 +57,7 @@ config USB_ARCH_HAS_OHCI
# some non-PCI hcds implement EHCI
config USB_ARCH_HAS_EHCI
boolean
- default y if PPC_83xx
+ default y if FSL_SOC
default y if SOC_AU1200
default y if ARCH_IXP4XX
default y if ARCH_W90X900
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH #upstream-fixes] pata_mpc52xx: inherit from ata_bmdma_port_ops
From: Roman Fietze @ 2011-01-10 7:26 UTC (permalink / raw)
To: Tejun Heo; +Cc: linux-ide, Jeff Garzik, linuxppc-dev, Sergei Shtylyov
In-Reply-To: <20110109224820.GB26607@mtj.dyndns.org>
Hello Tejun,
On Sunday, 09.January.2011 23:48:20 Tejun Heo wrote:
> Fix it.
I can confirm that, it's fixed.
Thank's a lot. Should have looked into it, that was really a simple
fix.
Roman
--
Roman Fietze Telemotive AG Buero Muehlhausen
Breitwiesen 73347 Muehlhausen
Tel.: +49(0)7335/18493-45 http://www.telemotive.de
^ permalink raw reply
* gianfar: incorrect TCP checksum when timestamps are enabled
From: Alex Dubov @ 2011-01-10 6:22 UTC (permalink / raw)
To: linuxppc-dev
Greetings.=0A=0AI'm working on MPC8548 based board (I started with 2.6.37-r=
c7, now upgraded=0Ato post release 2.6.37 git head).=0A=0AIt so appears, th=
at when tcp timestamps are enabled (default setting)=0ATCP checksums of out=
going SYN packets are calculated incorrectly. This=0Acauses remote machines=
to reject such packets, effectively preventing any=0Auseful network use. T=
he problem is reproducible every time.=0A=0AOther protocols appear to work =
reliably (UDP/DHCP do work).=0A=0AIf tcp timestamps are disabled, checksums=
are calculated correctly.=0A=0ANetdev guys tend to think that the problem =
is with hardware checksum=0Aoffloading, the theory I'm going to test now.=
=0A=0A=0A=0A
^ permalink raw reply
* [PATCH #upstream-fixes] pata_mpc52xx: inherit from ata_bmdma_port_ops
From: Tejun Heo @ 2011-01-09 22:48 UTC (permalink / raw)
To: Jeff Garzik; +Cc: linux-ide, linuxppc-dev, Sergei Shtylyov, Roman Fietze
In-Reply-To: <4D21FA4D.3030506@mvista.com>
pata_mpc52xx supports BMDMA but inherits ata_sff_port_ops which
triggers BUG_ON() when a DMA command is issued. Fix it.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Roman Fietze <roman.fietze@telemotive.de>
Cc: Sergei Shtylyov <sshtylyov@mvista.com>
Cc: stable@kernel.org
---
drivers/ata/pata_mpc52xx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index 8cc536e..d7d8026 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -610,7 +610,7 @@ static struct scsi_host_template mpc52xx_ata_sht = {
};
static struct ata_port_operations mpc52xx_ata_port_ops = {
- .inherits = &ata_sff_port_ops,
+ .inherits = &ata_bmdma_port_ops,
.sff_dev_select = mpc52xx_ata_dev_select,
.set_piomode = mpc52xx_ata_set_piomode,
.set_dmamode = mpc52xx_ata_set_dmamode,
^ permalink raw reply related
* [PATCH 1/2] powerpc/boot/dts: Install dts from the right directory
From: Ben Hutchings @ 2011-01-09 0:24 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras; +Cc: linuxppc-dev
The dts-installed variable is initialised using a wildcard path that
will be expanded relative to the build directory. Use the existing
variable dtstree to generate an absolute wildcard path that will work
when building in a separate directory.
Reported-by: Gerhard Pircher <gerhard_pircher@gmx.net>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Tested-by: Gerhard Pircher <gerhard_pircher@gmx.net> [against 2.6.32]
---
arch/powerpc/boot/Makefile | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 96deec6..8917816 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -368,7 +368,7 @@ INSTALL :=3D install
extra-installed :=3D $(patsubst $(obj)/%, $(DESTDIR)$(WRAPPER_OBJDIR)/%, =
$(extra-y))
hostprogs-installed :=3D $(patsubst %, $(DESTDIR)$(WRAPPER_BINDIR)/%, $(ho=
stprogs-y))
wrapper-installed :=3D $(DESTDIR)$(WRAPPER_BINDIR)/wrapper
-dts-installed :=3D $(patsubst $(obj)/dts/%, $(DESTDIR)$(WRAPPER_DTSDIR)/%=
, $(wildcard $(obj)/dts/*.dts))
+dts-installed :=3D $(patsubst $(dtstree)/%, $(DESTDIR)$(WRAPPER_DTSDIR)/%=
, $(wildcard $(dtstree)/*.dts))
=20
all-installed :=3D $(extra-installed) $(hostprogs-installed) $(wrapper-in=
stalled) $(dts-installed)
=20
--=20
1.7.2.3
^ permalink raw reply related
* [PATCH 2/2] powerpc/boot/Makefile: Use $(src) and $(obj) as per makefiles.txt
From: Ben Hutchings @ 2011-01-09 0:25 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1294532641.3283.70.camel@localhost>
$(src) and $(obj) are normally the same, but are supposed to be used
for paths under $(srctree) and $(objtree) respectively.
Also use $(dtstree) and $(wrapper) as appropriate.
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
This is totally untested, so please review carefully!
Ben.
arch/powerpc/boot/Makefile | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 8917816..bd7abba 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -33,7 +33,7 @@ ifeq ($(call cc-option-yn, -fstack-protector),y)
BOOTCFLAGS +=3D -fno-stack-protector
endif
=20
-BOOTCFLAGS +=3D -I$(obj) -I$(srctree)/$(obj)
+BOOTCFLAGS +=3D -I$(obj) -I$(srctree)/$(src)
=20
DTC_FLAGS ?=3D -p 1024
=20
@@ -399,10 +399,10 @@ $(extra-installed) : $(DESTDIR)$(WRAPPER_OBJDIR)/% : =
$(obj)/% | $(DESTDIR)$(WRAP
$(hostprogs-installed) : $(DESTDIR)$(WRAPPER_BINDIR)/% : $(obj)/% | $(DES=
TDIR)$(WRAPPER_BINDIR)
$(call cmd,install_exe)
=20
-$(dts-installed) : $(DESTDIR)$(WRAPPER_DTSDIR)/% : $(srctree)/$(obj)/dts/%=
| $(DESTDIR)$(WRAPPER_DTSDIR)
+$(dts-installed) : $(DESTDIR)$(WRAPPER_DTSDIR)/% : $(dtstree)/% | $(DESTDI=
R)$(WRAPPER_DTSDIR)
$(call cmd,install_dts)
=20
-$(wrapper-installed): $(DESTDIR)$(WRAPPER_BINDIR) $(srctree)/$(obj)/wrappe=
r | $(DESTDIR)$(WRAPPER_BINDIR)
+$(wrapper-installed): $(DESTDIR)$(WRAPPER_BINDIR) $(wrapper) | $(DESTDIR)$=
(WRAPPER_BINDIR)
$(call cmd,install_wrapper)
=20
$(obj)/bootwrapper_install: $(all-installed)
--=20
1.7.2.3
^ permalink raw reply related
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