diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-10 10:37:51 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-10 10:37:51 -0500 |
commit | 3ae0af12b458461f36dfddb26e54056be32928dd (patch) | |
tree | 063059f24f42506ce2a86374a3b6e2b7a8ae3fcf /arch | |
parent | 3b44f137b9a846c5452d9e6e1271b79b1dbcc942 (diff) | |
parent | 7c43ee40ec602db3fa27e6e2d4f092f06ab0901c (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc-merge
Diffstat (limited to 'arch')
95 files changed, 1909 insertions, 2003 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 1493c7896fe3..ed31062029f7 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -599,6 +599,10 @@ config HAVE_ARCH_EARLY_PFN_TO_NID | |||
599 | def_bool y | 599 | def_bool y |
600 | depends on NEED_MULTIPLE_NODES | 600 | depends on NEED_MULTIPLE_NODES |
601 | 601 | ||
602 | config ARCH_MEMORY_PROBE | ||
603 | def_bool y | ||
604 | depends on MEMORY_HOTPLUG | ||
605 | |||
602 | # Some NUMA nodes have memory ranges that span | 606 | # Some NUMA nodes have memory ranges that span |
603 | # other nodes. Even though a pfn is valid and | 607 | # other nodes. Even though a pfn is valid and |
604 | # between a node's start and end pfns, it may not | 608 | # between a node's start and end pfns, it may not |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index b3ae2993efb8..c04bbd320594 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | ifeq ($(CONFIG_PPC64),y) | 5 | ifeq ($(CONFIG_PPC64),y) |
6 | EXTRA_CFLAGS += -mno-minimal-toc | 6 | EXTRA_CFLAGS += -mno-minimal-toc |
7 | CFLAGS_ioctl32.o += -Ifs/ | ||
7 | endif | 8 | endif |
8 | ifeq ($(CONFIG_PPC32),y) | 9 | ifeq ($(CONFIG_PPC32),y) |
9 | CFLAGS_prom_init.o += -fPIC | 10 | CFLAGS_prom_init.o += -fPIC |
@@ -11,15 +12,21 @@ CFLAGS_btext.o += -fPIC | |||
11 | endif | 12 | endif |
12 | 13 | ||
13 | obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ | 14 | obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ |
14 | signal_32.o pmc.o | 15 | irq.o signal_32.o pmc.o |
15 | obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ | 16 | obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ |
16 | signal_64.o ptrace32.o systbl.o | 17 | signal_64.o ptrace32.o systbl.o \ |
18 | paca.o ioctl32.o cpu_setup_power4.o \ | ||
19 | firmware.o sysfs.o | ||
17 | obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o | 20 | obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o |
18 | obj-$(CONFIG_POWER4) += idle_power4.o | 21 | obj-$(CONFIG_POWER4) += idle_power4.o |
19 | obj-$(CONFIG_PPC_OF) += of_device.o | 22 | obj-$(CONFIG_PPC_OF) += of_device.o |
20 | obj-$(CONFIG_PPC_RTAS) += rtas.o | 23 | procfs-$(CONFIG_PPC64) := proc_ppc64.o |
24 | obj-$(CONFIG_PROC_FS) += $(procfs-y) | ||
25 | rtaspci-$(CONFIG_PPC64) := rtas_pci.o | ||
26 | obj-$(CONFIG_PPC_RTAS) += rtas.o $(rtaspci-y) | ||
21 | obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o | 27 | obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o |
22 | obj-$(CONFIG_RTAS_PROC) += rtas-proc.o | 28 | obj-$(CONFIG_RTAS_PROC) += rtas-proc.o |
29 | obj-$(CONFIG_LPARCFG) += lparcfg.o | ||
23 | obj-$(CONFIG_IBMVIO) += vio.o | 30 | obj-$(CONFIG_IBMVIO) += vio.o |
24 | obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o | 31 | obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o |
25 | 32 | ||
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index b75757251994..8793102711a8 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -106,7 +106,6 @@ int main(void) | |||
106 | DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); | 106 | DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); |
107 | DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); | 107 | DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); |
108 | DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); | 108 | DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); |
109 | DEFINE(PLATFORM, offsetof(struct systemcfg, platform)); | ||
110 | DEFINE(PLATFORM_LPAR, PLATFORM_LPAR); | 109 | DEFINE(PLATFORM_LPAR, PLATFORM_LPAR); |
111 | 110 | ||
112 | /* paca */ | 111 | /* paca */ |
diff --git a/arch/ppc64/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S index 1fb673c511ff..cca942fe6115 100644 --- a/arch/ppc64/kernel/cpu_setup_power4.S +++ b/arch/powerpc/kernel/cpu_setup_power4.S | |||
@@ -114,11 +114,11 @@ _GLOBAL(__setup_cpu_ppc970) | |||
114 | 114 | ||
115 | .data | 115 | .data |
116 | .balign L1_CACHE_BYTES,0 | 116 | .balign L1_CACHE_BYTES,0 |
117 | cpu_state_storage: | 117 | cpu_state_storage: |
118 | .space CS_SIZE | 118 | .space CS_SIZE |
119 | .balign L1_CACHE_BYTES,0 | 119 | .balign L1_CACHE_BYTES,0 |
120 | .text | 120 | .text |
121 | 121 | ||
122 | /* Called in normal context to backup CPU 0 state. This | 122 | /* Called in normal context to backup CPU 0 state. This |
123 | * does not include cache settings. This function is also | 123 | * does not include cache settings. This function is also |
124 | * called for machine sleep. This does not include the MMU | 124 | * called for machine sleep. This does not include the MMU |
@@ -151,7 +151,7 @@ _GLOBAL(__save_cpu_setup) | |||
151 | std r3,CS_HID4(r5) | 151 | std r3,CS_HID4(r5) |
152 | mfspr r3,SPRN_HID5 | 152 | mfspr r3,SPRN_HID5 |
153 | std r3,CS_HID5(r5) | 153 | std r3,CS_HID5(r5) |
154 | 154 | ||
155 | 2: | 155 | 2: |
156 | mtcr r7 | 156 | mtcr r7 |
157 | blr | 157 | blr |
@@ -213,7 +213,7 @@ _GLOBAL(__restore_cpu_setup) | |||
213 | mtspr SPRN_HID1,r3 | 213 | mtspr SPRN_HID1,r3 |
214 | sync | 214 | sync |
215 | isync | 215 | isync |
216 | 216 | ||
217 | /* Restore HID4 */ | 217 | /* Restore HID4 */ |
218 | ld r3,CS_HID4(r5) | 218 | ld r3,CS_HID4(r5) |
219 | sync | 219 | sync |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index cc4e9eb1c13f..1d85cedbbb7b 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -52,6 +52,9 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); | |||
52 | #define COMMON_USER (PPC_FEATURE_32 | PPC_FEATURE_HAS_FPU | \ | 52 | #define COMMON_USER (PPC_FEATURE_32 | PPC_FEATURE_HAS_FPU | \ |
53 | PPC_FEATURE_HAS_MMU) | 53 | PPC_FEATURE_HAS_MMU) |
54 | #define COMMON_USER_PPC64 (COMMON_USER | PPC_FEATURE_64) | 54 | #define COMMON_USER_PPC64 (COMMON_USER | PPC_FEATURE_64) |
55 | #define COMMON_USER_POWER4 (COMMON_USER_PPC64 | PPC_FEATURE_POWER4) | ||
56 | #define COMMON_USER_POWER5 (COMMON_USER_PPC64 | PPC_FEATURE_POWER5) | ||
57 | #define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS) | ||
55 | 58 | ||
56 | 59 | ||
57 | /* We only set the spe features if the kernel was compiled with | 60 | /* We only set the spe features if the kernel was compiled with |
@@ -160,7 +163,7 @@ struct cpu_spec cpu_specs[] = { | |||
160 | .pvr_value = 0x00350000, | 163 | .pvr_value = 0x00350000, |
161 | .cpu_name = "POWER4 (gp)", | 164 | .cpu_name = "POWER4 (gp)", |
162 | .cpu_features = CPU_FTRS_POWER4, | 165 | .cpu_features = CPU_FTRS_POWER4, |
163 | .cpu_user_features = COMMON_USER_PPC64, | 166 | .cpu_user_features = COMMON_USER_POWER4, |
164 | .icache_bsize = 128, | 167 | .icache_bsize = 128, |
165 | .dcache_bsize = 128, | 168 | .dcache_bsize = 128, |
166 | .num_pmcs = 8, | 169 | .num_pmcs = 8, |
@@ -175,7 +178,7 @@ struct cpu_spec cpu_specs[] = { | |||
175 | .pvr_value = 0x00380000, | 178 | .pvr_value = 0x00380000, |
176 | .cpu_name = "POWER4+ (gq)", | 179 | .cpu_name = "POWER4+ (gq)", |
177 | .cpu_features = CPU_FTRS_POWER4, | 180 | .cpu_features = CPU_FTRS_POWER4, |
178 | .cpu_user_features = COMMON_USER_PPC64, | 181 | .cpu_user_features = COMMON_USER_POWER4, |
179 | .icache_bsize = 128, | 182 | .icache_bsize = 128, |
180 | .dcache_bsize = 128, | 183 | .dcache_bsize = 128, |
181 | .num_pmcs = 8, | 184 | .num_pmcs = 8, |
@@ -190,7 +193,7 @@ struct cpu_spec cpu_specs[] = { | |||
190 | .pvr_value = 0x00390000, | 193 | .pvr_value = 0x00390000, |
191 | .cpu_name = "PPC970", | 194 | .cpu_name = "PPC970", |
192 | .cpu_features = CPU_FTRS_PPC970, | 195 | .cpu_features = CPU_FTRS_PPC970, |
193 | .cpu_user_features = COMMON_USER_PPC64 | | 196 | .cpu_user_features = COMMON_USER_POWER4 | |
194 | PPC_FEATURE_HAS_ALTIVEC_COMP, | 197 | PPC_FEATURE_HAS_ALTIVEC_COMP, |
195 | .icache_bsize = 128, | 198 | .icache_bsize = 128, |
196 | .dcache_bsize = 128, | 199 | .dcache_bsize = 128, |
@@ -212,7 +215,7 @@ struct cpu_spec cpu_specs[] = { | |||
212 | #else | 215 | #else |
213 | .cpu_features = CPU_FTRS_PPC970, | 216 | .cpu_features = CPU_FTRS_PPC970, |
214 | #endif | 217 | #endif |
215 | .cpu_user_features = COMMON_USER_PPC64 | | 218 | .cpu_user_features = COMMON_USER_POWER4 | |
216 | PPC_FEATURE_HAS_ALTIVEC_COMP, | 219 | PPC_FEATURE_HAS_ALTIVEC_COMP, |
217 | .icache_bsize = 128, | 220 | .icache_bsize = 128, |
218 | .dcache_bsize = 128, | 221 | .dcache_bsize = 128, |
@@ -230,7 +233,7 @@ struct cpu_spec cpu_specs[] = { | |||
230 | .pvr_value = 0x00440000, | 233 | .pvr_value = 0x00440000, |
231 | .cpu_name = "PPC970MP", | 234 | .cpu_name = "PPC970MP", |
232 | .cpu_features = CPU_FTRS_PPC970, | 235 | .cpu_features = CPU_FTRS_PPC970, |
233 | .cpu_user_features = COMMON_USER_PPC64 | | 236 | .cpu_user_features = COMMON_USER_POWER4 | |
234 | PPC_FEATURE_HAS_ALTIVEC_COMP, | 237 | PPC_FEATURE_HAS_ALTIVEC_COMP, |
235 | .icache_bsize = 128, | 238 | .icache_bsize = 128, |
236 | .dcache_bsize = 128, | 239 | .dcache_bsize = 128, |
@@ -245,7 +248,7 @@ struct cpu_spec cpu_specs[] = { | |||
245 | .pvr_value = 0x003a0000, | 248 | .pvr_value = 0x003a0000, |
246 | .cpu_name = "POWER5 (gr)", | 249 | .cpu_name = "POWER5 (gr)", |
247 | .cpu_features = CPU_FTRS_POWER5, | 250 | .cpu_features = CPU_FTRS_POWER5, |
248 | .cpu_user_features = COMMON_USER_PPC64, | 251 | .cpu_user_features = COMMON_USER_POWER5, |
249 | .icache_bsize = 128, | 252 | .icache_bsize = 128, |
250 | .dcache_bsize = 128, | 253 | .dcache_bsize = 128, |
251 | .num_pmcs = 6, | 254 | .num_pmcs = 6, |
@@ -260,7 +263,7 @@ struct cpu_spec cpu_specs[] = { | |||
260 | .pvr_value = 0x003b0000, | 263 | .pvr_value = 0x003b0000, |
261 | .cpu_name = "POWER5 (gs)", | 264 | .cpu_name = "POWER5 (gs)", |
262 | .cpu_features = CPU_FTRS_POWER5, | 265 | .cpu_features = CPU_FTRS_POWER5, |
263 | .cpu_user_features = COMMON_USER_PPC64, | 266 | .cpu_user_features = COMMON_USER_POWER5_PLUS, |
264 | .icache_bsize = 128, | 267 | .icache_bsize = 128, |
265 | .dcache_bsize = 128, | 268 | .dcache_bsize = 128, |
266 | .num_pmcs = 6, | 269 | .num_pmcs = 6, |
@@ -276,7 +279,7 @@ struct cpu_spec cpu_specs[] = { | |||
276 | .cpu_name = "Cell Broadband Engine", | 279 | .cpu_name = "Cell Broadband Engine", |
277 | .cpu_features = CPU_FTRS_CELL, | 280 | .cpu_features = CPU_FTRS_CELL, |
278 | .cpu_user_features = COMMON_USER_PPC64 | | 281 | .cpu_user_features = COMMON_USER_PPC64 | |
279 | PPC_FEATURE_HAS_ALTIVEC_COMP, | 282 | PPC_FEATURE_CELL | PPC_FEATURE_HAS_ALTIVEC_COMP, |
280 | .icache_bsize = 128, | 283 | .icache_bsize = 128, |
281 | .dcache_bsize = 128, | 284 | .dcache_bsize = 128, |
282 | .cpu_setup = __setup_cpu_be, | 285 | .cpu_setup = __setup_cpu_be, |
diff --git a/arch/ppc64/kernel/firmware.c b/arch/powerpc/kernel/firmware.c index d8432c0fb27d..65eae752a527 100644 --- a/arch/ppc64/kernel/firmware.c +++ b/arch/powerpc/kernel/firmware.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/kernel/firmware.c | ||
3 | * | ||
4 | * Extracted from cputable.c | 2 | * Extracted from cputable.c |
5 | * | 3 | * |
6 | * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org) | 4 | * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org) |
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index 4d6001fa1cf2..b780b42c95fc 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S | |||
@@ -41,20 +41,20 @@ _GLOBAL(load_up_fpu) | |||
41 | #ifndef CONFIG_SMP | 41 | #ifndef CONFIG_SMP |
42 | LOADBASE(r3, last_task_used_math) | 42 | LOADBASE(r3, last_task_used_math) |
43 | toreal(r3) | 43 | toreal(r3) |
44 | LDL r4,OFF(last_task_used_math)(r3) | 44 | PPC_LL r4,OFF(last_task_used_math)(r3) |
45 | CMPI 0,r4,0 | 45 | PPC_LCMPI 0,r4,0 |
46 | beq 1f | 46 | beq 1f |
47 | toreal(r4) | 47 | toreal(r4) |
48 | addi r4,r4,THREAD /* want last_task_used_math->thread */ | 48 | addi r4,r4,THREAD /* want last_task_used_math->thread */ |
49 | SAVE_32FPRS(0, r4) | 49 | SAVE_32FPRS(0, r4) |
50 | mffs fr0 | 50 | mffs fr0 |
51 | stfd fr0,THREAD_FPSCR(r4) | 51 | stfd fr0,THREAD_FPSCR(r4) |
52 | LDL r5,PT_REGS(r4) | 52 | PPC_LL r5,PT_REGS(r4) |
53 | toreal(r5) | 53 | toreal(r5) |
54 | LDL r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 54 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
55 | li r10,MSR_FP|MSR_FE0|MSR_FE1 | 55 | li r10,MSR_FP|MSR_FE0|MSR_FE1 |
56 | andc r4,r4,r10 /* disable FP for previous task */ | 56 | andc r4,r4,r10 /* disable FP for previous task */ |
57 | STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 57 | PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
58 | 1: | 58 | 1: |
59 | #endif /* CONFIG_SMP */ | 59 | #endif /* CONFIG_SMP */ |
60 | /* enable use of FP after return */ | 60 | /* enable use of FP after return */ |
@@ -77,7 +77,7 @@ _GLOBAL(load_up_fpu) | |||
77 | #ifndef CONFIG_SMP | 77 | #ifndef CONFIG_SMP |
78 | subi r4,r5,THREAD | 78 | subi r4,r5,THREAD |
79 | fromreal(r4) | 79 | fromreal(r4) |
80 | STL r4,OFF(last_task_used_math)(r3) | 80 | PPC_STL r4,OFF(last_task_used_math)(r3) |
81 | #endif /* CONFIG_SMP */ | 81 | #endif /* CONFIG_SMP */ |
82 | /* restore registers and return */ | 82 | /* restore registers and return */ |
83 | /* we haven't used ctr or xer or lr */ | 83 | /* we haven't used ctr or xer or lr */ |
@@ -97,24 +97,24 @@ _GLOBAL(giveup_fpu) | |||
97 | MTMSRD(r5) /* enable use of fpu now */ | 97 | MTMSRD(r5) /* enable use of fpu now */ |
98 | SYNC_601 | 98 | SYNC_601 |
99 | isync | 99 | isync |
100 | CMPI 0,r3,0 | 100 | PPC_LCMPI 0,r3,0 |
101 | beqlr- /* if no previous owner, done */ | 101 | beqlr- /* if no previous owner, done */ |
102 | addi r3,r3,THREAD /* want THREAD of task */ | 102 | addi r3,r3,THREAD /* want THREAD of task */ |
103 | LDL r5,PT_REGS(r3) | 103 | PPC_LL r5,PT_REGS(r3) |
104 | CMPI 0,r5,0 | 104 | PPC_LCMPI 0,r5,0 |
105 | SAVE_32FPRS(0, r3) | 105 | SAVE_32FPRS(0, r3) |
106 | mffs fr0 | 106 | mffs fr0 |
107 | stfd fr0,THREAD_FPSCR(r3) | 107 | stfd fr0,THREAD_FPSCR(r3) |
108 | beq 1f | 108 | beq 1f |
109 | LDL r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 109 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
110 | li r3,MSR_FP|MSR_FE0|MSR_FE1 | 110 | li r3,MSR_FP|MSR_FE0|MSR_FE1 |
111 | andc r4,r4,r3 /* disable FP for previous task */ | 111 | andc r4,r4,r3 /* disable FP for previous task */ |
112 | STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 112 | PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
113 | 1: | 113 | 1: |
114 | #ifndef CONFIG_SMP | 114 | #ifndef CONFIG_SMP |
115 | li r5,0 | 115 | li r5,0 |
116 | LOADBASE(r4,last_task_used_math) | 116 | LOADBASE(r4,last_task_used_math) |
117 | STL r5,OFF(last_task_used_math)(r4) | 117 | PPC_STL r5,OFF(last_task_used_math)(r4) |
118 | #endif /* CONFIG_SMP */ | 118 | #endif /* CONFIG_SMP */ |
119 | blr | 119 | blr |
120 | 120 | ||
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 16ab40daa738..8a8bf79ef044 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <asm/reg.h> | 28 | #include <asm/reg.h> |
29 | #include <asm/page.h> | 29 | #include <asm/page.h> |
30 | #include <asm/mmu.h> | 30 | #include <asm/mmu.h> |
31 | #include <asm/systemcfg.h> | ||
32 | #include <asm/ppc_asm.h> | 31 | #include <asm/ppc_asm.h> |
33 | #include <asm/asm-offsets.h> | 32 | #include <asm/asm-offsets.h> |
34 | #include <asm/bug.h> | 33 | #include <asm/bug.h> |
@@ -1697,25 +1696,14 @@ _GLOBAL(pmac_secondary_start) | |||
1697 | * SPRG3 = paca virtual address | 1696 | * SPRG3 = paca virtual address |
1698 | */ | 1697 | */ |
1699 | _GLOBAL(__secondary_start) | 1698 | _GLOBAL(__secondary_start) |
1699 | /* Set thread priority to MEDIUM */ | ||
1700 | HMT_MEDIUM | ||
1700 | 1701 | ||
1701 | HMT_MEDIUM /* Set thread priority to MEDIUM */ | 1702 | /* Load TOC */ |
1702 | |||
1703 | ld r2,PACATOC(r13) | 1703 | ld r2,PACATOC(r13) |
1704 | li r6,0 | 1704 | |
1705 | stb r6,PACAPROCENABLED(r13) | 1705 | /* Do early setup for that CPU (stab, slb, hash table pointer) */ |
1706 | 1706 | bl .early_setup_secondary | |
1707 | #ifndef CONFIG_PPC_ISERIES | ||
1708 | /* Initialize the page table pointer register. */ | ||
1709 | LOADADDR(r6,_SDR1) | ||
1710 | ld r6,0(r6) /* get the value of _SDR1 */ | ||
1711 | mtspr SPRN_SDR1,r6 /* set the htab location */ | ||
1712 | #endif | ||
1713 | /* Initialize the first segment table (or SLB) entry */ | ||
1714 | ld r3,PACASTABVIRT(r13) /* get addr of segment table */ | ||
1715 | BEGIN_FTR_SECTION | ||
1716 | bl .stab_initialize | ||
1717 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | ||
1718 | bl .slb_initialize | ||
1719 | 1707 | ||
1720 | /* Initialize the kernel stack. Just a repeat for iSeries. */ | 1708 | /* Initialize the kernel stack. Just a repeat for iSeries. */ |
1721 | LOADADDR(r3,current_set) | 1709 | LOADADDR(r3,current_set) |
@@ -1724,37 +1712,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | |||
1724 | addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD | 1712 | addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD |
1725 | std r1,PACAKSAVE(r13) | 1713 | std r1,PACAKSAVE(r13) |
1726 | 1714 | ||
1727 | ld r3,PACASTABREAL(r13) /* get raddr of segment table */ | 1715 | /* Clear backchain so we get nice backtraces */ |
1728 | ori r4,r3,1 /* turn on valid bit */ | ||
1729 | |||
1730 | #ifdef CONFIG_PPC_ISERIES | ||
1731 | li r0,-1 /* hypervisor call */ | ||
1732 | li r3,1 | ||
1733 | sldi r3,r3,63 /* 0x8000000000000000 */ | ||
1734 | ori r3,r3,4 /* 0x8000000000000004 */ | ||
1735 | sc /* HvCall_setASR */ | ||
1736 | #else | ||
1737 | /* set the ASR */ | ||
1738 | ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */ | ||
1739 | ld r3,0(r3) | ||
1740 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ | ||
1741 | andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ | ||
1742 | beq 98f /* branch if result is 0 */ | ||
1743 | mfspr r3,SPRN_PVR | ||
1744 | srwi r3,r3,16 | ||
1745 | cmpwi r3,0x37 /* SStar */ | ||
1746 | beq 97f | ||
1747 | cmpwi r3,0x36 /* IStar */ | ||
1748 | beq 97f | ||
1749 | cmpwi r3,0x34 /* Pulsar */ | ||
1750 | bne 98f | ||
1751 | 97: li r3,H_SET_ASR /* hcall = H_SET_ASR */ | ||
1752 | HVSC /* Invoking hcall */ | ||
1753 | b 99f | ||
1754 | 98: /* !(rpa hypervisor) || !(star) */ | ||
1755 | mtasr r4 /* set the stab location */ | ||
1756 | 99: | ||
1757 | #endif | ||
1758 | li r7,0 | 1716 | li r7,0 |
1759 | mtlr r7 | 1717 | mtlr r7 |
1760 | 1718 | ||
@@ -1777,6 +1735,7 @@ _GLOBAL(start_secondary_prolog) | |||
1777 | li r3,0 | 1735 | li r3,0 |
1778 | std r3,0(r1) /* Zero the stack frame pointer */ | 1736 | std r3,0(r1) /* Zero the stack frame pointer */ |
1779 | bl .start_secondary | 1737 | bl .start_secondary |
1738 | b . | ||
1780 | #endif | 1739 | #endif |
1781 | 1740 | ||
1782 | /* | 1741 | /* |
@@ -1896,40 +1855,6 @@ _STATIC(start_here_multiplatform) | |||
1896 | mr r3,r31 | 1855 | mr r3,r31 |
1897 | bl .early_setup | 1856 | bl .early_setup |
1898 | 1857 | ||
1899 | /* set the ASR */ | ||
1900 | ld r3,PACASTABREAL(r13) | ||
1901 | ori r4,r3,1 /* turn on valid bit */ | ||
1902 | ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */ | ||
1903 | ld r3,0(r3) | ||
1904 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ | ||
1905 | andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ | ||
1906 | beq 98f /* branch if result is 0 */ | ||
1907 | mfspr r3,SPRN_PVR | ||
1908 | srwi r3,r3,16 | ||
1909 | cmpwi r3,0x37 /* SStar */ | ||
1910 | beq 97f | ||
1911 | cmpwi r3,0x36 /* IStar */ | ||
1912 | beq 97f | ||
1913 | cmpwi r3,0x34 /* Pulsar */ | ||
1914 | bne 98f | ||
1915 | 97: li r3,H_SET_ASR /* hcall = H_SET_ASR */ | ||
1916 | HVSC /* Invoking hcall */ | ||
1917 | b 99f | ||
1918 | 98: /* !(rpa hypervisor) || !(star) */ | ||
1919 | mtasr r4 /* set the stab location */ | ||
1920 | 99: | ||
1921 | /* Set SDR1 (hash table pointer) */ | ||
1922 | ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */ | ||
1923 | ld r3,0(r3) | ||
1924 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ | ||
1925 | /* Test if bit 0 is set (LPAR bit) */ | ||
1926 | andi. r3,r3,PLATFORM_LPAR | ||
1927 | bne 98f /* branch if result is !0 */ | ||
1928 | LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ | ||
1929 | add r6,r6,r26 | ||
1930 | ld r6,0(r6) /* get the value of _SDR1 */ | ||
1931 | mtspr SPRN_SDR1,r6 /* set the htab location */ | ||
1932 | 98: | ||
1933 | LOADADDR(r3,.start_here_common) | 1858 | LOADADDR(r3,.start_here_common) |
1934 | SET_REG_TO_CONST(r4, MSR_KERNEL) | 1859 | SET_REG_TO_CONST(r4, MSR_KERNEL) |
1935 | mtspr SPRN_SRR0,r3 | 1860 | mtspr SPRN_SRR0,r3 |
diff --git a/arch/ppc64/kernel/ioctl32.c b/arch/powerpc/kernel/ioctl32.c index ba4a899045c2..3fa6a93adbd0 100644 --- a/arch/ppc64/kernel/ioctl32.c +++ b/arch/powerpc/kernel/ioctl32.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * ioctl32.c: Conversion between 32bit and 64bit native ioctls. | 2 | * ioctl32.c: Conversion between 32bit and 64bit native ioctls. |
3 | * | 3 | * |
4 | * Based on sparc64 ioctl32.c by: | 4 | * Based on sparc64 ioctl32.c by: |
5 | * | 5 | * |
6 | * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) | 6 | * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) |
diff --git a/arch/ppc64/kernel/irq.c b/arch/powerpc/kernel/irq.c index 87474584033f..4b7940693f3d 100644 --- a/arch/ppc64/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -5,12 +5,12 @@ | |||
5 | * Copyright (C) 1992 Linus Torvalds | 5 | * Copyright (C) 1992 Linus Torvalds |
6 | * Adapted from arch/i386 by Gary Thomas | 6 | * Adapted from arch/i386 by Gary Thomas |
7 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | 7 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) |
8 | * Updated and modified by Cort Dougan (cort@cs.nmt.edu) | 8 | * Updated and modified by Cort Dougan <cort@fsmlabs.com> |
9 | * Copyright (C) 1996 Cort Dougan | 9 | * Copyright (C) 1996-2001 Cort Dougan |
10 | * Adapted for Power Macintosh by Paul Mackerras | 10 | * Adapted for Power Macintosh by Paul Mackerras |
11 | * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) | 11 | * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) |
12 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | 12 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). |
13 | * | 13 | * |
14 | * This program is free software; you can redistribute it and/or | 14 | * This program is free software; you can redistribute it and/or |
15 | * modify it under the terms of the GNU General Public License | 15 | * modify it under the terms of the GNU General Public License |
16 | * as published by the Free Software Foundation; either version | 16 | * as published by the Free Software Foundation; either version |
@@ -21,6 +21,14 @@ | |||
21 | * instead of just grabbing them. Thus setups with different IRQ numbers | 21 | * instead of just grabbing them. Thus setups with different IRQ numbers |
22 | * shouldn't result in any weird surprises, and installing new handlers | 22 | * shouldn't result in any weird surprises, and installing new handlers |
23 | * should be easier. | 23 | * should be easier. |
24 | * | ||
25 | * The MPC8xx has an interrupt mask in the SIU. If a bit is set, the | ||
26 | * interrupt is _enabled_. As expected, IRQ0 is bit 0 in the 32-bit | ||
27 | * mask register (of which only 16 are defined), hence the weird shifting | ||
28 | * and complement of the cached_irq_mask. I want to be able to stuff | ||
29 | * this right into the SIU SMASK register. | ||
30 | * Many of the prep/chrp functions are conditional compiled on CONFIG_8xx | ||
31 | * to reduce code space and undefined function references. | ||
24 | */ | 32 | */ |
25 | 33 | ||
26 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
@@ -29,6 +37,7 @@ | |||
29 | #include <linux/kernel_stat.h> | 37 | #include <linux/kernel_stat.h> |
30 | #include <linux/signal.h> | 38 | #include <linux/signal.h> |
31 | #include <linux/sched.h> | 39 | #include <linux/sched.h> |
40 | #include <linux/ptrace.h> | ||
32 | #include <linux/ioport.h> | 41 | #include <linux/ioport.h> |
33 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
34 | #include <linux/timex.h> | 43 | #include <linux/timex.h> |
@@ -40,9 +49,13 @@ | |||
40 | #include <linux/irq.h> | 49 | #include <linux/irq.h> |
41 | #include <linux/proc_fs.h> | 50 | #include <linux/proc_fs.h> |
42 | #include <linux/random.h> | 51 | #include <linux/random.h> |
43 | #include <linux/kallsyms.h> | 52 | #include <linux/seq_file.h> |
53 | #include <linux/cpumask.h> | ||
44 | #include <linux/profile.h> | 54 | #include <linux/profile.h> |
45 | #include <linux/bitops.h> | 55 | #include <linux/bitops.h> |
56 | #ifdef CONFIG_PPC64 | ||
57 | #include <linux/kallsyms.h> | ||
58 | #endif | ||
46 | 59 | ||
47 | #include <asm/uaccess.h> | 60 | #include <asm/uaccess.h> |
48 | #include <asm/system.h> | 61 | #include <asm/system.h> |
@@ -52,35 +65,54 @@ | |||
52 | #include <asm/cache.h> | 65 | #include <asm/cache.h> |
53 | #include <asm/prom.h> | 66 | #include <asm/prom.h> |
54 | #include <asm/ptrace.h> | 67 | #include <asm/ptrace.h> |
55 | #include <asm/iseries/it_lp_queue.h> | ||
56 | #include <asm/machdep.h> | 68 | #include <asm/machdep.h> |
69 | #ifdef CONFIG_PPC64 | ||
70 | #include <asm/iseries/it_lp_queue.h> | ||
57 | #include <asm/paca.h> | 71 | #include <asm/paca.h> |
72 | #endif | ||
58 | 73 | ||
59 | #ifdef CONFIG_SMP | 74 | static int ppc_spurious_interrupts; |
60 | extern void iSeries_smp_message_recv( struct pt_regs * ); | 75 | |
76 | #if defined(CONFIG_PPC_ISERIES) && defined(CONFIG_SMP) | ||
77 | extern void iSeries_smp_message_recv(struct pt_regs *); | ||
78 | #endif | ||
79 | |||
80 | #ifdef CONFIG_PPC32 | ||
81 | #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) | ||
82 | |||
83 | unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; | ||
84 | atomic_t ppc_n_lost_interrupts; | ||
85 | |||
86 | #ifdef CONFIG_TAU_INT | ||
87 | extern int tau_initialized; | ||
88 | extern int tau_interrupts(int); | ||
89 | #endif | ||
90 | |||
91 | #if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE) | ||
92 | extern atomic_t ipi_recv; | ||
93 | extern atomic_t ipi_sent; | ||
61 | #endif | 94 | #endif |
95 | #endif /* CONFIG_PPC32 */ | ||
62 | 96 | ||
63 | extern irq_desc_t irq_desc[NR_IRQS]; | 97 | #ifdef CONFIG_PPC64 |
64 | EXPORT_SYMBOL(irq_desc); | 98 | EXPORT_SYMBOL(irq_desc); |
65 | 99 | ||
66 | int distribute_irqs = 1; | 100 | int distribute_irqs = 1; |
67 | int __irq_offset_value; | 101 | int __irq_offset_value; |
68 | int ppc_spurious_interrupts; | ||
69 | u64 ppc64_interrupt_controller; | 102 | u64 ppc64_interrupt_controller; |
103 | #endif /* CONFIG_PPC64 */ | ||
70 | 104 | ||
71 | int show_interrupts(struct seq_file *p, void *v) | 105 | int show_interrupts(struct seq_file *p, void *v) |
72 | { | 106 | { |
73 | int i = *(loff_t *) v, j; | 107 | int i = *(loff_t *)v, j; |
74 | struct irqaction * action; | 108 | struct irqaction *action; |
75 | irq_desc_t *desc; | 109 | irq_desc_t *desc; |
76 | unsigned long flags; | 110 | unsigned long flags; |
77 | 111 | ||
78 | if (i == 0) { | 112 | if (i == 0) { |
79 | seq_printf(p, " "); | 113 | seq_puts(p, " "); |
80 | for (j=0; j<NR_CPUS; j++) { | 114 | for_each_online_cpu(j) |
81 | if (cpu_online(j)) | 115 | seq_printf(p, "CPU%d ", j); |
82 | seq_printf(p, "CPU%d ",j); | ||
83 | } | ||
84 | seq_putc(p, '\n'); | 116 | seq_putc(p, '\n'); |
85 | } | 117 | } |
86 | 118 | ||
@@ -92,26 +124,41 @@ int show_interrupts(struct seq_file *p, void *v) | |||
92 | goto skip; | 124 | goto skip; |
93 | seq_printf(p, "%3d: ", i); | 125 | seq_printf(p, "%3d: ", i); |
94 | #ifdef CONFIG_SMP | 126 | #ifdef CONFIG_SMP |
95 | for (j = 0; j < NR_CPUS; j++) { | 127 | for_each_online_cpu(j) |
96 | if (cpu_online(j)) | 128 | seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); |
97 | seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); | ||
98 | } | ||
99 | #else | 129 | #else |
100 | seq_printf(p, "%10u ", kstat_irqs(i)); | 130 | seq_printf(p, "%10u ", kstat_irqs(i)); |
101 | #endif /* CONFIG_SMP */ | 131 | #endif /* CONFIG_SMP */ |
102 | if (desc->handler) | 132 | if (desc->handler) |
103 | seq_printf(p, " %s ", desc->handler->typename ); | 133 | seq_printf(p, " %s ", desc->handler->typename); |
104 | else | 134 | else |
105 | seq_printf(p, " None "); | 135 | seq_puts(p, " None "); |
106 | seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge "); | 136 | seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge "); |
107 | seq_printf(p, " %s",action->name); | 137 | seq_printf(p, " %s", action->name); |
108 | for (action=action->next; action; action = action->next) | 138 | for (action = action->next; action; action = action->next) |
109 | seq_printf(p, ", %s", action->name); | 139 | seq_printf(p, ", %s", action->name); |
110 | seq_putc(p, '\n'); | 140 | seq_putc(p, '\n'); |
111 | skip: | 141 | skip: |
112 | spin_unlock_irqrestore(&desc->lock, flags); | 142 | spin_unlock_irqrestore(&desc->lock, flags); |
113 | } else if (i == NR_IRQS) | 143 | } else if (i == NR_IRQS) { |
144 | #ifdef CONFIG_PPC32 | ||
145 | #ifdef CONFIG_TAU_INT | ||
146 | if (tau_initialized){ | ||
147 | seq_puts(p, "TAU: "); | ||
148 | for (j = 0; j < NR_CPUS; j++) | ||
149 | if (cpu_online(j)) | ||
150 | seq_printf(p, "%10u ", tau_interrupts(j)); | ||
151 | seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); | ||
152 | } | ||
153 | #endif | ||
154 | #if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE) | ||
155 | /* should this be per processor send/receive? */ | ||
156 | seq_printf(p, "IPI (recv/sent): %10u/%u\n", | ||
157 | atomic_read(&ipi_recv), atomic_read(&ipi_sent)); | ||
158 | #endif | ||
159 | #endif /* CONFIG_PPC32 */ | ||
114 | seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); | 160 | seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); |
161 | } | ||
115 | return 0; | 162 | return 0; |
116 | } | 163 | } |
117 | 164 | ||
@@ -144,126 +191,6 @@ void fixup_irqs(cpumask_t map) | |||
144 | } | 191 | } |
145 | #endif | 192 | #endif |
146 | 193 | ||
147 | extern int noirqdebug; | ||
148 | |||
149 | /* | ||
150 | * Eventually, this should take an array of interrupts and an array size | ||
151 | * so it can dispatch multiple interrupts. | ||
152 | */ | ||
153 | void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) | ||
154 | { | ||
155 | int status; | ||
156 | struct irqaction *action; | ||
157 | int cpu = smp_processor_id(); | ||
158 | irq_desc_t *desc = get_irq_desc(irq); | ||
159 | irqreturn_t action_ret; | ||
160 | #ifdef CONFIG_IRQSTACKS | ||
161 | struct thread_info *curtp, *irqtp; | ||
162 | #endif | ||
163 | |||
164 | kstat_cpu(cpu).irqs[irq]++; | ||
165 | |||
166 | if (desc->status & IRQ_PER_CPU) { | ||
167 | /* no locking required for CPU-local interrupts: */ | ||
168 | ack_irq(irq); | ||
169 | action_ret = handle_IRQ_event(irq, regs, desc->action); | ||
170 | desc->handler->end(irq); | ||
171 | return; | ||
172 | } | ||
173 | |||
174 | spin_lock(&desc->lock); | ||
175 | ack_irq(irq); | ||
176 | /* | ||
177 | REPLAY is when Linux resends an IRQ that was dropped earlier | ||
178 | WAITING is used by probe to mark irqs that are being tested | ||
179 | */ | ||
180 | status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); | ||
181 | status |= IRQ_PENDING; /* we _want_ to handle it */ | ||
182 | |||
183 | /* | ||
184 | * If the IRQ is disabled for whatever reason, we cannot | ||
185 | * use the action we have. | ||
186 | */ | ||
187 | action = NULL; | ||
188 | if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { | ||
189 | action = desc->action; | ||
190 | if (!action || !action->handler) { | ||
191 | ppc_spurious_interrupts++; | ||
192 | printk(KERN_DEBUG "Unhandled interrupt %x, disabled\n", irq); | ||
193 | /* We can't call disable_irq here, it would deadlock */ | ||
194 | if (!desc->depth) | ||
195 | desc->depth = 1; | ||
196 | desc->status |= IRQ_DISABLED; | ||
197 | /* This is not a real spurrious interrupt, we | ||
198 | * have to eoi it, so we jump to out | ||
199 | */ | ||
200 | mask_irq(irq); | ||
201 | goto out; | ||
202 | } | ||
203 | status &= ~IRQ_PENDING; /* we commit to handling */ | ||
204 | status |= IRQ_INPROGRESS; /* we are handling it */ | ||
205 | } | ||
206 | desc->status = status; | ||
207 | |||
208 | /* | ||
209 | * If there is no IRQ handler or it was disabled, exit early. | ||
210 | Since we set PENDING, if another processor is handling | ||
211 | a different instance of this same irq, the other processor | ||
212 | will take care of it. | ||
213 | */ | ||
214 | if (unlikely(!action)) | ||
215 | goto out; | ||
216 | |||
217 | /* | ||
218 | * Edge triggered interrupts need to remember | ||
219 | * pending events. | ||
220 | * This applies to any hw interrupts that allow a second | ||
221 | * instance of the same irq to arrive while we are in do_IRQ | ||
222 | * or in the handler. But the code here only handles the _second_ | ||
223 | * instance of the irq, not the third or fourth. So it is mostly | ||
224 | * useful for irq hardware that does not mask cleanly in an | ||
225 | * SMP environment. | ||
226 | */ | ||
227 | for (;;) { | ||
228 | spin_unlock(&desc->lock); | ||
229 | |||
230 | #ifdef CONFIG_IRQSTACKS | ||
231 | /* Switch to the irq stack to handle this */ | ||
232 | curtp = current_thread_info(); | ||
233 | irqtp = hardirq_ctx[smp_processor_id()]; | ||
234 | if (curtp != irqtp) { | ||
235 | irqtp->task = curtp->task; | ||
236 | irqtp->flags = 0; | ||
237 | action_ret = call_handle_IRQ_event(irq, regs, action, irqtp); | ||
238 | irqtp->task = NULL; | ||
239 | if (irqtp->flags) | ||
240 | set_bits(irqtp->flags, &curtp->flags); | ||
241 | } else | ||
242 | #endif | ||
243 | action_ret = handle_IRQ_event(irq, regs, action); | ||
244 | |||
245 | spin_lock(&desc->lock); | ||
246 | if (!noirqdebug) | ||
247 | note_interrupt(irq, desc, action_ret, regs); | ||
248 | if (likely(!(desc->status & IRQ_PENDING))) | ||
249 | break; | ||
250 | desc->status &= ~IRQ_PENDING; | ||
251 | } | ||
252 | out: | ||
253 | desc->status &= ~IRQ_INPROGRESS; | ||
254 | /* | ||
255 | * The ->end() handler has to deal with interrupts which got | ||
256 | * disabled while the handler was running. | ||
257 | */ | ||
258 | if (desc->handler) { | ||
259 | if (desc->handler->end) | ||
260 | desc->handler->end(irq); | ||
261 | else if (desc->handler->enable) | ||
262 | desc->handler->enable(irq); | ||
263 | } | ||
264 | spin_unlock(&desc->lock); | ||
265 | } | ||
266 | |||
267 | #ifdef CONFIG_PPC_ISERIES | 194 | #ifdef CONFIG_PPC_ISERIES |
268 | void do_IRQ(struct pt_regs *regs) | 195 | void do_IRQ(struct pt_regs *regs) |
269 | { | 196 | { |
@@ -310,8 +237,11 @@ void do_IRQ(struct pt_regs *regs) | |||
310 | void do_IRQ(struct pt_regs *regs) | 237 | void do_IRQ(struct pt_regs *regs) |
311 | { | 238 | { |
312 | int irq; | 239 | int irq; |
240 | #ifdef CONFIG_IRQSTACKS | ||
241 | struct thread_info *curtp, *irqtp; | ||
242 | #endif | ||
313 | 243 | ||
314 | irq_enter(); | 244 | irq_enter(); |
315 | 245 | ||
316 | #ifdef CONFIG_DEBUG_STACKOVERFLOW | 246 | #ifdef CONFIG_DEBUG_STACKOVERFLOW |
317 | /* Debugging check for stack overflow: is there less than 2KB free? */ | 247 | /* Debugging check for stack overflow: is there less than 2KB free? */ |
@@ -328,20 +258,44 @@ void do_IRQ(struct pt_regs *regs) | |||
328 | } | 258 | } |
329 | #endif | 259 | #endif |
330 | 260 | ||
261 | /* | ||
262 | * Every platform is required to implement ppc_md.get_irq. | ||
263 | * This function will either return an irq number or -1 to | ||
264 | * indicate there are no more pending. | ||
265 | * The value -2 is for buggy hardware and means that this IRQ | ||
266 | * has already been handled. -- Tom | ||
267 | */ | ||
331 | irq = ppc_md.get_irq(regs); | 268 | irq = ppc_md.get_irq(regs); |
332 | 269 | ||
333 | if (irq >= 0) | 270 | if (irq >= 0) { |
334 | ppc_irq_dispatch_handler(regs, irq); | 271 | #ifdef CONFIG_IRQSTACKS |
335 | else | 272 | /* Switch to the irq stack to handle this */ |
336 | /* That's not SMP safe ... but who cares ? */ | 273 | curtp = current_thread_info(); |
337 | ppc_spurious_interrupts++; | 274 | irqtp = hardirq_ctx[smp_processor_id()]; |
338 | 275 | if (curtp != irqtp) { | |
339 | irq_exit(); | 276 | irqtp->task = curtp->task; |
277 | irqtp->flags = 0; | ||
278 | call___do_IRQ(irq, regs, irqtp); | ||
279 | irqtp->task = NULL; | ||
280 | if (irqtp->flags) | ||
281 | set_bits(irqtp->flags, &curtp->flags); | ||
282 | } else | ||
283 | #endif | ||
284 | __do_IRQ(irq, regs); | ||
285 | } else | ||
286 | #ifdef CONFIG_PPC32 | ||
287 | if (irq != -2) | ||
288 | #endif | ||
289 | /* That's not SMP safe ... but who cares ? */ | ||
290 | ppc_spurious_interrupts++; | ||
291 | irq_exit(); | ||
340 | } | 292 | } |
293 | |||
341 | #endif /* CONFIG_PPC_ISERIES */ | 294 | #endif /* CONFIG_PPC_ISERIES */ |
342 | 295 | ||
343 | void __init init_IRQ(void) | 296 | void __init init_IRQ(void) |
344 | { | 297 | { |
298 | #ifdef CONFIG_PPC64 | ||
345 | static int once = 0; | 299 | static int once = 0; |
346 | 300 | ||
347 | if (once) | 301 | if (once) |
@@ -349,10 +303,14 @@ void __init init_IRQ(void) | |||
349 | 303 | ||
350 | once++; | 304 | once++; |
351 | 305 | ||
306 | #endif | ||
352 | ppc_md.init_IRQ(); | 307 | ppc_md.init_IRQ(); |
308 | #ifdef CONFIG_PPC64 | ||
353 | irq_ctx_init(); | 309 | irq_ctx_init(); |
310 | #endif | ||
354 | } | 311 | } |
355 | 312 | ||
313 | #ifdef CONFIG_PPC64 | ||
356 | #ifndef CONFIG_PPC_ISERIES | 314 | #ifndef CONFIG_PPC_ISERIES |
357 | /* | 315 | /* |
358 | * Virtual IRQ mapping code, used on systems with XICS interrupt controllers. | 316 | * Virtual IRQ mapping code, used on systems with XICS interrupt controllers. |
@@ -517,3 +475,4 @@ static int __init setup_noirqdistrib(char *str) | |||
517 | } | 475 | } |
518 | 476 | ||
519 | __setup("noirqdistrib", setup_noirqdistrib); | 477 | __setup("noirqdistrib", setup_noirqdistrib); |
478 | #endif /* CONFIG_PPC64 */ | ||
diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 3e7b2f28ec83..5e954fae031f 100644 --- a/arch/ppc64/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <asm/time.h> | 35 | #include <asm/time.h> |
36 | #include <asm/iseries/it_exp_vpd_panel.h> | 36 | #include <asm/iseries/it_exp_vpd_panel.h> |
37 | #include <asm/prom.h> | 37 | #include <asm/prom.h> |
38 | #include <asm/systemcfg.h> | ||
38 | 39 | ||
39 | #define MODULE_VERS "1.6" | 40 | #define MODULE_VERS "1.6" |
40 | #define MODULE_NAME "lparcfg" | 41 | #define MODULE_NAME "lparcfg" |
@@ -96,7 +97,7 @@ static unsigned long get_purr(void) | |||
96 | 97 | ||
97 | #define lparcfg_write NULL | 98 | #define lparcfg_write NULL |
98 | 99 | ||
99 | /* | 100 | /* |
100 | * Methods used to fetch LPAR data when running on an iSeries platform. | 101 | * Methods used to fetch LPAR data when running on an iSeries platform. |
101 | */ | 102 | */ |
102 | static int lparcfg_data(struct seq_file *m, void *v) | 103 | static int lparcfg_data(struct seq_file *m, void *v) |
@@ -168,7 +169,7 @@ static int lparcfg_data(struct seq_file *m, void *v) | |||
168 | #endif /* CONFIG_PPC_ISERIES */ | 169 | #endif /* CONFIG_PPC_ISERIES */ |
169 | 170 | ||
170 | #ifdef CONFIG_PPC_PSERIES | 171 | #ifdef CONFIG_PPC_PSERIES |
171 | /* | 172 | /* |
172 | * Methods used to fetch LPAR data when running on a pSeries platform. | 173 | * Methods used to fetch LPAR data when running on a pSeries platform. |
173 | */ | 174 | */ |
174 | 175 | ||
@@ -177,7 +178,7 @@ static int lparcfg_data(struct seq_file *m, void *v) | |||
177 | * entitled_capacity,unallocated_capacity, | 178 | * entitled_capacity,unallocated_capacity, |
178 | * aggregation, resource_capability). | 179 | * aggregation, resource_capability). |
179 | * | 180 | * |
180 | * R4 = Entitled Processor Capacity Percentage. | 181 | * R4 = Entitled Processor Capacity Percentage. |
181 | * R5 = Unallocated Processor Capacity Percentage. | 182 | * R5 = Unallocated Processor Capacity Percentage. |
182 | * R6 (AABBCCDDEEFFGGHH). | 183 | * R6 (AABBCCDDEEFFGGHH). |
183 | * XXXX - reserved (0) | 184 | * XXXX - reserved (0) |
@@ -190,7 +191,7 @@ static int lparcfg_data(struct seq_file *m, void *v) | |||
190 | * XX - variable processor Capacity Weight | 191 | * XX - variable processor Capacity Weight |
191 | * XX - Unallocated Variable Processor Capacity Weight. | 192 | * XX - Unallocated Variable Processor Capacity Weight. |
192 | * XXXX - Active processors in Physical Processor Pool. | 193 | * XXXX - Active processors in Physical Processor Pool. |
193 | * XXXX - Processors active on platform. | 194 | * XXXX - Processors active on platform. |
194 | */ | 195 | */ |
195 | static unsigned int h_get_ppp(unsigned long *entitled, | 196 | static unsigned int h_get_ppp(unsigned long *entitled, |
196 | unsigned long *unallocated, | 197 | unsigned long *unallocated, |
@@ -273,7 +274,7 @@ static void parse_system_parameter_string(struct seq_file *m) | |||
273 | if (!workbuffer) { | 274 | if (!workbuffer) { |
274 | printk(KERN_ERR "%s %s kmalloc failure at line %d \n", | 275 | printk(KERN_ERR "%s %s kmalloc failure at line %d \n", |
275 | __FILE__, __FUNCTION__, __LINE__); | 276 | __FILE__, __FUNCTION__, __LINE__); |
276 | kfree(local_buffer); | 277 | kfree(local_buffer); |
277 | return; | 278 | return; |
278 | } | 279 | } |
279 | #ifdef LPARCFG_DEBUG | 280 | #ifdef LPARCFG_DEBUG |
@@ -371,7 +372,7 @@ static int lparcfg_data(struct seq_file *m, void *v) | |||
371 | lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL); | 372 | lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL); |
372 | 373 | ||
373 | if (lrdrp == NULL) { | 374 | if (lrdrp == NULL) { |
374 | partition_potential_processors = systemcfg->processorCount; | 375 | partition_potential_processors = _systemcfg->processorCount; |
375 | } else { | 376 | } else { |
376 | partition_potential_processors = *(lrdrp + 4); | 377 | partition_potential_processors = *(lrdrp + 4); |
377 | } | 378 | } |
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 3bedb532aed9..f6d84a75ed26 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
@@ -519,7 +519,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | |||
519 | * | 519 | * |
520 | * flush_icache_range(unsigned long start, unsigned long stop) | 520 | * flush_icache_range(unsigned long start, unsigned long stop) |
521 | */ | 521 | */ |
522 | _GLOBAL(flush_icache_range) | 522 | _GLOBAL(__flush_icache_range) |
523 | BEGIN_FTR_SECTION | 523 | BEGIN_FTR_SECTION |
524 | blr /* for 601, do nothing */ | 524 | blr /* for 601, do nothing */ |
525 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 525 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) |
@@ -607,27 +607,6 @@ _GLOBAL(invalidate_dcache_range) | |||
607 | sync /* wait for dcbi's to get to ram */ | 607 | sync /* wait for dcbi's to get to ram */ |
608 | blr | 608 | blr |
609 | 609 | ||
610 | #ifdef CONFIG_NOT_COHERENT_CACHE | ||
611 | /* | ||
612 | * 40x cores have 8K or 16K dcache and 32 byte line size. | ||
613 | * 44x has a 32K dcache and 32 byte line size. | ||
614 | * 8xx has 1, 2, 4, 8K variants. | ||
615 | * For now, cover the worst case of the 44x. | ||
616 | * Must be called with external interrupts disabled. | ||
617 | */ | ||
618 | #define CACHE_NWAYS 64 | ||
619 | #define CACHE_NLINES 16 | ||
620 | |||
621 | _GLOBAL(flush_dcache_all) | ||
622 | li r4, (2 * CACHE_NWAYS * CACHE_NLINES) | ||
623 | mtctr r4 | ||
624 | lis r5, KERNELBASE@h | ||
625 | 1: lwz r3, 0(r5) /* Load one word from every line */ | ||
626 | addi r5, r5, L1_CACHE_BYTES | ||
627 | bdnz 1b | ||
628 | blr | ||
629 | #endif /* CONFIG_NOT_COHERENT_CACHE */ | ||
630 | |||
631 | /* | 610 | /* |
632 | * Flush a particular page from the data cache to RAM. | 611 | * Flush a particular page from the data cache to RAM. |
633 | * Note: this is necessary because the instruction cache does *not* | 612 | * Note: this is necessary because the instruction cache does *not* |
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index ae1433da09b2..ae48a002f81a 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S | |||
@@ -89,12 +89,12 @@ _GLOBAL(call_do_softirq) | |||
89 | mtlr r0 | 89 | mtlr r0 |
90 | blr | 90 | blr |
91 | 91 | ||
92 | _GLOBAL(call_handle_IRQ_event) | 92 | _GLOBAL(call___do_IRQ) |
93 | mflr r0 | 93 | mflr r0 |
94 | std r0,16(r1) | 94 | std r0,16(r1) |
95 | stdu r1,THREAD_SIZE-112(r6) | 95 | stdu r1,THREAD_SIZE-112(r5) |
96 | mr r1,r6 | 96 | mr r1,r5 |
97 | bl .handle_IRQ_event | 97 | bl .__do_IRQ |
98 | ld r1,0(r1) | 98 | ld r1,0(r1) |
99 | ld r0,16(r1) | 99 | ld r0,16(r1) |
100 | mtlr r0 | 100 | mtlr r0 |
diff --git a/arch/ppc64/kernel/pacaData.c b/arch/powerpc/kernel/paca.c index 3133c72b28ec..3cf2517c5f91 100644 --- a/arch/ppc64/kernel/pacaData.c +++ b/arch/powerpc/kernel/paca.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <asm/processor.h> | 15 | #include <asm/processor.h> |
16 | #include <asm/ptrace.h> | 16 | #include <asm/ptrace.h> |
17 | #include <asm/page.h> | 17 | #include <asm/page.h> |
18 | 18 | #include <asm/systemcfg.h> | |
19 | #include <asm/lppaca.h> | 19 | #include <asm/lppaca.h> |
20 | #include <asm/iseries/it_lp_queue.h> | 20 | #include <asm/iseries/it_lp_queue.h> |
21 | #include <asm/paca.h> | 21 | #include <asm/paca.h> |
@@ -24,15 +24,14 @@ static union { | |||
24 | struct systemcfg data; | 24 | struct systemcfg data; |
25 | u8 page[PAGE_SIZE]; | 25 | u8 page[PAGE_SIZE]; |
26 | } systemcfg_store __attribute__((__section__(".data.page.aligned"))); | 26 | } systemcfg_store __attribute__((__section__(".data.page.aligned"))); |
27 | struct systemcfg *systemcfg = &systemcfg_store.data; | 27 | struct systemcfg *_systemcfg = &systemcfg_store.data; |
28 | EXPORT_SYMBOL(systemcfg); | ||
29 | 28 | ||
30 | 29 | ||
31 | /* This symbol is provided by the linker - let it fill in the paca | 30 | /* This symbol is provided by the linker - let it fill in the paca |
32 | * field correctly */ | 31 | * field correctly */ |
33 | extern unsigned long __toc_start; | 32 | extern unsigned long __toc_start; |
34 | 33 | ||
35 | /* The Paca is an array with one entry per processor. Each contains an | 34 | /* The Paca is an array with one entry per processor. Each contains an |
36 | * lppaca, which contains the information shared between the | 35 | * lppaca, which contains the information shared between the |
37 | * hypervisor and Linux. Each also contains an ItLpRegSave area which | 36 | * hypervisor and Linux. Each also contains an ItLpRegSave area which |
38 | * is used by the hypervisor to save registers. | 37 | * is used by the hypervisor to save registers. |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 47d6f7e2ea9f..5dcf4ba05ee8 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <asm/cputable.h> | 44 | #include <asm/cputable.h> |
45 | #include <asm/btext.h> | 45 | #include <asm/btext.h> |
46 | #include <asm/div64.h> | 46 | #include <asm/div64.h> |
47 | #include <asm/signal.h> | ||
47 | 48 | ||
48 | #ifdef CONFIG_8xx | 49 | #ifdef CONFIG_8xx |
49 | #include <asm/commproc.h> | 50 | #include <asm/commproc.h> |
@@ -56,7 +57,6 @@ extern void machine_check_exception(struct pt_regs *regs); | |||
56 | extern void alignment_exception(struct pt_regs *regs); | 57 | extern void alignment_exception(struct pt_regs *regs); |
57 | extern void program_check_exception(struct pt_regs *regs); | 58 | extern void program_check_exception(struct pt_regs *regs); |
58 | extern void single_step_exception(struct pt_regs *regs); | 59 | extern void single_step_exception(struct pt_regs *regs); |
59 | extern int do_signal(sigset_t *, struct pt_regs *); | ||
60 | extern int pmac_newworld; | 60 | extern int pmac_newworld; |
61 | extern int sys_sigreturn(struct pt_regs *regs); | 61 | extern int sys_sigreturn(struct pt_regs *regs); |
62 | 62 | ||
@@ -188,9 +188,6 @@ EXPORT_SYMBOL(adb_try_handler_change); | |||
188 | EXPORT_SYMBOL(cuda_request); | 188 | EXPORT_SYMBOL(cuda_request); |
189 | EXPORT_SYMBOL(cuda_poll); | 189 | EXPORT_SYMBOL(cuda_poll); |
190 | #endif /* CONFIG_ADB_CUDA */ | 190 | #endif /* CONFIG_ADB_CUDA */ |
191 | #if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_PPC32) | ||
192 | EXPORT_SYMBOL(_machine); | ||
193 | #endif | ||
194 | #ifdef CONFIG_PPC_PMAC | 191 | #ifdef CONFIG_PPC_PMAC |
195 | EXPORT_SYMBOL(sys_ctrler); | 192 | EXPORT_SYMBOL(sys_ctrler); |
196 | #endif | 193 | #endif |
diff --git a/arch/ppc64/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c index 24e955ee9487..a1c19502fe8b 100644 --- a/arch/ppc64/kernel/proc_ppc64.c +++ b/arch/powerpc/kernel/proc_ppc64.c | |||
@@ -1,18 +1,16 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/kernel/proc_ppc64.c | ||
3 | * | ||
4 | * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation | 2 | * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation |
5 | * | 3 | * |
6 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; either version 2 of the License, or | 6 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. | 7 | * (at your option) any later version. |
10 | * | 8 | * |
11 | * This program is distributed in the hope that it will be useful, | 9 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
15 | * | 13 | * |
16 | * You should have received a copy of the GNU General Public License | 14 | * You should have received a copy of the GNU General Public License |
17 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
@@ -53,7 +51,7 @@ static int __init proc_ppc64_create(void) | |||
53 | if (!root) | 51 | if (!root) |
54 | return 1; | 52 | return 1; |
55 | 53 | ||
56 | if (!(systemcfg->platform & (PLATFORM_PSERIES | PLATFORM_CELL))) | 54 | if (!(platform_is_pseries() || _machine == PLATFORM_CELL)) |
57 | return 0; | 55 | return 0; |
58 | 56 | ||
59 | if (!proc_mkdir("rtas", root)) | 57 | if (!proc_mkdir("rtas", root)) |
@@ -74,7 +72,7 @@ static int __init proc_ppc64_init(void) | |||
74 | if (!pde) | 72 | if (!pde) |
75 | return 1; | 73 | return 1; |
76 | pde->nlink = 1; | 74 | pde->nlink = 1; |
77 | pde->data = systemcfg; | 75 | pde->data = _systemcfg; |
78 | pde->size = PAGE_SIZE; | 76 | pde->size = PAGE_SIZE; |
79 | pde->proc_fops = &page_map_fops; | 77 | pde->proc_fops = &page_map_fops; |
80 | 78 | ||
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index f645adb57534..6a5b468edb4d 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -48,9 +48,6 @@ | |||
48 | #include <asm/machdep.h> | 48 | #include <asm/machdep.h> |
49 | #include <asm/pSeries_reconfig.h> | 49 | #include <asm/pSeries_reconfig.h> |
50 | #include <asm/pci-bridge.h> | 50 | #include <asm/pci-bridge.h> |
51 | #ifdef CONFIG_PPC64 | ||
52 | #include <asm/systemcfg.h> | ||
53 | #endif | ||
54 | 51 | ||
55 | #ifdef DEBUG | 52 | #ifdef DEBUG |
56 | #define DBG(fmt...) printk(KERN_ERR fmt) | 53 | #define DBG(fmt...) printk(KERN_ERR fmt) |
@@ -74,10 +71,6 @@ struct isa_reg_property { | |||
74 | typedef int interpret_func(struct device_node *, unsigned long *, | 71 | typedef int interpret_func(struct device_node *, unsigned long *, |
75 | int, int, int); | 72 | int, int, int); |
76 | 73 | ||
77 | extern struct rtas_t rtas; | ||
78 | extern struct lmb lmb; | ||
79 | extern unsigned long klimit; | ||
80 | |||
81 | static int __initdata dt_root_addr_cells; | 74 | static int __initdata dt_root_addr_cells; |
82 | static int __initdata dt_root_size_cells; | 75 | static int __initdata dt_root_size_cells; |
83 | 76 | ||
@@ -391,7 +384,7 @@ static int __devinit finish_node_interrupts(struct device_node *np, | |||
391 | 384 | ||
392 | #ifdef CONFIG_PPC64 | 385 | #ifdef CONFIG_PPC64 |
393 | /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ | 386 | /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ |
394 | if (systemcfg->platform == PLATFORM_POWERMAC && ic && ic->parent) { | 387 | if (_machine == PLATFORM_POWERMAC && ic && ic->parent) { |
395 | char *name = get_property(ic->parent, "name", NULL); | 388 | char *name = get_property(ic->parent, "name", NULL); |
396 | if (name && !strcmp(name, "u3")) | 389 | if (name && !strcmp(name, "u3")) |
397 | np->intrs[intrcount].line += 128; | 390 | np->intrs[intrcount].line += 128; |
@@ -1087,9 +1080,9 @@ void __init unflatten_device_tree(void) | |||
1087 | static int __init early_init_dt_scan_cpus(unsigned long node, | 1080 | static int __init early_init_dt_scan_cpus(unsigned long node, |
1088 | const char *uname, int depth, void *data) | 1081 | const char *uname, int depth, void *data) |
1089 | { | 1082 | { |
1090 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | ||
1091 | u32 *prop; | 1083 | u32 *prop; |
1092 | unsigned long size = 0; | 1084 | unsigned long size; |
1085 | char *type = of_get_flat_dt_prop(node, "device_type", &size); | ||
1093 | 1086 | ||
1094 | /* We are scanning "cpu" nodes only */ | 1087 | /* We are scanning "cpu" nodes only */ |
1095 | if (type == NULL || strcmp(type, "cpu") != 0) | 1088 | if (type == NULL || strcmp(type, "cpu") != 0) |
@@ -1115,7 +1108,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
1115 | 1108 | ||
1116 | #ifdef CONFIG_ALTIVEC | 1109 | #ifdef CONFIG_ALTIVEC |
1117 | /* Check if we have a VMX and eventually update CPU features */ | 1110 | /* Check if we have a VMX and eventually update CPU features */ |
1118 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", &size); | 1111 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", NULL); |
1119 | if (prop && (*prop) > 0) { | 1112 | if (prop && (*prop) > 0) { |
1120 | cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; | 1113 | cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; |
1121 | cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; | 1114 | cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; |
@@ -1161,13 +1154,9 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
1161 | prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); | 1154 | prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); |
1162 | if (prop == NULL) | 1155 | if (prop == NULL) |
1163 | return 0; | 1156 | return 0; |
1164 | #ifdef CONFIG_PPC64 | ||
1165 | systemcfg->platform = *prop; | ||
1166 | #else | ||
1167 | #ifdef CONFIG_PPC_MULTIPLATFORM | 1157 | #ifdef CONFIG_PPC_MULTIPLATFORM |
1168 | _machine = *prop; | 1158 | _machine = *prop; |
1169 | #endif | 1159 | #endif |
1170 | #endif | ||
1171 | 1160 | ||
1172 | #ifdef CONFIG_PPC64 | 1161 | #ifdef CONFIG_PPC64 |
1173 | /* check if iommu is forced on or off */ | 1162 | /* check if iommu is forced on or off */ |
@@ -1264,7 +1253,14 @@ static int __init early_init_dt_scan_memory(unsigned long node, | |||
1264 | unsigned long l; | 1253 | unsigned long l; |
1265 | 1254 | ||
1266 | /* We are scanning "memory" nodes only */ | 1255 | /* We are scanning "memory" nodes only */ |
1267 | if (type == NULL || strcmp(type, "memory") != 0) | 1256 | if (type == NULL) { |
1257 | /* | ||
1258 | * The longtrail doesn't have a device_type on the | ||
1259 | * /memory node, so look for the node called /memory@0. | ||
1260 | */ | ||
1261 | if (depth != 1 || strcmp(uname, "memory@0") != 0) | ||
1262 | return 0; | ||
1263 | } else if (strcmp(type, "memory") != 0) | ||
1268 | return 0; | 1264 | return 0; |
1269 | 1265 | ||
1270 | reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); | 1266 | reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); |
@@ -1339,9 +1335,6 @@ void __init early_init_devtree(void *params) | |||
1339 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); | 1335 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); |
1340 | lmb_enforce_memory_limit(memory_limit); | 1336 | lmb_enforce_memory_limit(memory_limit); |
1341 | lmb_analyze(); | 1337 | lmb_analyze(); |
1342 | #ifdef CONFIG_PPC64 | ||
1343 | systemcfg->physicalMemorySize = lmb_phys_mem_size(); | ||
1344 | #endif | ||
1345 | lmb_reserve(0, __pa(klimit)); | 1338 | lmb_reserve(0, __pa(klimit)); |
1346 | 1339 | ||
1347 | DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); | 1340 | DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); |
@@ -1908,7 +1901,7 @@ static int of_finish_dynamic_node(struct device_node *node, | |||
1908 | /* We don't support that function on PowerMac, at least | 1901 | /* We don't support that function on PowerMac, at least |
1909 | * not yet | 1902 | * not yet |
1910 | */ | 1903 | */ |
1911 | if (systemcfg->platform == PLATFORM_POWERMAC) | 1904 | if (_machine == PLATFORM_POWERMAC) |
1912 | return -ENODEV; | 1905 | return -ENODEV; |
1913 | 1906 | ||
1914 | /* fix up new node's linux_phandle field */ | 1907 | /* fix up new node's linux_phandle field */ |
@@ -1992,9 +1985,11 @@ int prom_add_property(struct device_node* np, struct property* prop) | |||
1992 | *next = prop; | 1985 | *next = prop; |
1993 | write_unlock(&devtree_lock); | 1986 | write_unlock(&devtree_lock); |
1994 | 1987 | ||
1988 | #ifdef CONFIG_PROC_DEVICETREE | ||
1995 | /* try to add to proc as well if it was initialized */ | 1989 | /* try to add to proc as well if it was initialized */ |
1996 | if (np->pde) | 1990 | if (np->pde) |
1997 | proc_device_tree_add_prop(np->pde, prop); | 1991 | proc_device_tree_add_prop(np->pde, prop); |
1992 | #endif /* CONFIG_PROC_DEVICETREE */ | ||
1998 | 1993 | ||
1999 | return 0; | 1994 | return 0; |
2000 | } | 1995 | } |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 6dc33d19fc2a..4ce0105c308e 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -94,11 +94,17 @@ extern const struct linux_logo logo_linux_clut224; | |||
94 | #ifdef CONFIG_PPC64 | 94 | #ifdef CONFIG_PPC64 |
95 | #define RELOC(x) (*PTRRELOC(&(x))) | 95 | #define RELOC(x) (*PTRRELOC(&(x))) |
96 | #define ADDR(x) (u32) add_reloc_offset((unsigned long)(x)) | 96 | #define ADDR(x) (u32) add_reloc_offset((unsigned long)(x)) |
97 | #define OF_WORKAROUNDS 0 | ||
97 | #else | 98 | #else |
98 | #define RELOC(x) (x) | 99 | #define RELOC(x) (x) |
99 | #define ADDR(x) (u32) (x) | 100 | #define ADDR(x) (u32) (x) |
101 | #define OF_WORKAROUNDS of_workarounds | ||
102 | int of_workarounds; | ||
100 | #endif | 103 | #endif |
101 | 104 | ||
105 | #define OF_WA_CLAIM 1 /* do phys/virt claim separately, then map */ | ||
106 | #define OF_WA_LONGTRAIL 2 /* work around longtrail bugs */ | ||
107 | |||
102 | #define PROM_BUG() do { \ | 108 | #define PROM_BUG() do { \ |
103 | prom_printf("kernel BUG at %s line 0x%x!\n", \ | 109 | prom_printf("kernel BUG at %s line 0x%x!\n", \ |
104 | RELOC(__FILE__), __LINE__); \ | 110 | RELOC(__FILE__), __LINE__); \ |
@@ -111,11 +117,6 @@ extern const struct linux_logo logo_linux_clut224; | |||
111 | #define prom_debug(x...) | 117 | #define prom_debug(x...) |
112 | #endif | 118 | #endif |
113 | 119 | ||
114 | #ifdef CONFIG_PPC32 | ||
115 | #define PLATFORM_POWERMAC _MACH_Pmac | ||
116 | #define PLATFORM_CHRP _MACH_chrp | ||
117 | #endif | ||
118 | |||
119 | 120 | ||
120 | typedef u32 prom_arg_t; | 121 | typedef u32 prom_arg_t; |
121 | 122 | ||
@@ -128,10 +129,11 @@ struct prom_args { | |||
128 | 129 | ||
129 | struct prom_t { | 130 | struct prom_t { |
130 | ihandle root; | 131 | ihandle root; |
131 | ihandle chosen; | 132 | phandle chosen; |
132 | int cpu; | 133 | int cpu; |
133 | ihandle stdout; | 134 | ihandle stdout; |
134 | ihandle mmumap; | 135 | ihandle mmumap; |
136 | ihandle memory; | ||
135 | }; | 137 | }; |
136 | 138 | ||
137 | struct mem_map_entry { | 139 | struct mem_map_entry { |
@@ -360,16 +362,36 @@ static void __init prom_printf(const char *format, ...) | |||
360 | static unsigned int __init prom_claim(unsigned long virt, unsigned long size, | 362 | static unsigned int __init prom_claim(unsigned long virt, unsigned long size, |
361 | unsigned long align) | 363 | unsigned long align) |
362 | { | 364 | { |
363 | int ret; | ||
364 | struct prom_t *_prom = &RELOC(prom); | 365 | struct prom_t *_prom = &RELOC(prom); |
365 | 366 | ||
366 | ret = call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size, | 367 | if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) { |
367 | (prom_arg_t)align); | 368 | /* |
368 | if (ret != -1 && _prom->mmumap != 0) | 369 | * Old OF requires we claim physical and virtual separately |
369 | /* old pmacs need us to map as well */ | 370 | * and then map explicitly (assuming virtual mode) |
371 | */ | ||
372 | int ret; | ||
373 | prom_arg_t result; | ||
374 | |||
375 | ret = call_prom_ret("call-method", 5, 2, &result, | ||
376 | ADDR("claim"), _prom->memory, | ||
377 | align, size, virt); | ||
378 | if (ret != 0 || result == -1) | ||
379 | return -1; | ||
380 | ret = call_prom_ret("call-method", 5, 2, &result, | ||
381 | ADDR("claim"), _prom->mmumap, | ||
382 | align, size, virt); | ||
383 | if (ret != 0) { | ||
384 | call_prom("call-method", 4, 1, ADDR("release"), | ||
385 | _prom->memory, size, virt); | ||
386 | return -1; | ||
387 | } | ||
388 | /* the 0x12 is M (coherence) + PP == read/write */ | ||
370 | call_prom("call-method", 6, 1, | 389 | call_prom("call-method", 6, 1, |
371 | ADDR("map"), _prom->mmumap, 0, size, virt, virt); | 390 | ADDR("map"), _prom->mmumap, 0x12, size, virt, virt); |
372 | return ret; | 391 | return virt; |
392 | } | ||
393 | return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size, | ||
394 | (prom_arg_t)align); | ||
373 | } | 395 | } |
374 | 396 | ||
375 | static void __init __attribute__((noreturn)) prom_panic(const char *reason) | 397 | static void __init __attribute__((noreturn)) prom_panic(const char *reason) |
@@ -415,11 +437,52 @@ static int inline prom_getproplen(phandle node, const char *pname) | |||
415 | return call_prom("getproplen", 2, 1, node, ADDR(pname)); | 437 | return call_prom("getproplen", 2, 1, node, ADDR(pname)); |
416 | } | 438 | } |
417 | 439 | ||
418 | static int inline prom_setprop(phandle node, const char *pname, | 440 | static void add_string(char **str, const char *q) |
419 | void *value, size_t valuelen) | ||
420 | { | 441 | { |
421 | return call_prom("setprop", 4, 1, node, ADDR(pname), | 442 | char *p = *str; |
422 | (u32)(unsigned long) value, (u32) valuelen); | 443 | |
444 | while (*q) | ||
445 | *p++ = *q++; | ||
446 | *p++ = ' '; | ||
447 | *str = p; | ||
448 | } | ||
449 | |||
450 | static char *tohex(unsigned int x) | ||
451 | { | ||
452 | static char digits[] = "0123456789abcdef"; | ||
453 | static char result[9]; | ||
454 | int i; | ||
455 | |||
456 | result[8] = 0; | ||
457 | i = 8; | ||
458 | do { | ||
459 | --i; | ||
460 | result[i] = digits[x & 0xf]; | ||
461 | x >>= 4; | ||
462 | } while (x != 0 && i > 0); | ||
463 | return &result[i]; | ||
464 | } | ||
465 | |||
466 | static int __init prom_setprop(phandle node, const char *nodename, | ||
467 | const char *pname, void *value, size_t valuelen) | ||
468 | { | ||
469 | char cmd[256], *p; | ||
470 | |||
471 | if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL)) | ||
472 | return call_prom("setprop", 4, 1, node, ADDR(pname), | ||
473 | (u32)(unsigned long) value, (u32) valuelen); | ||
474 | |||
475 | /* gah... setprop doesn't work on longtrail, have to use interpret */ | ||
476 | p = cmd; | ||
477 | add_string(&p, "dev"); | ||
478 | add_string(&p, nodename); | ||
479 | add_string(&p, tohex((u32)(unsigned long) value)); | ||
480 | add_string(&p, tohex(valuelen)); | ||
481 | add_string(&p, tohex(ADDR(pname))); | ||
482 | add_string(&p, tohex(strlen(RELOC(pname)))); | ||
483 | add_string(&p, "property"); | ||
484 | *p = 0; | ||
485 | return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd); | ||
423 | } | 486 | } |
424 | 487 | ||
425 | /* We can't use the standard versions because of RELOC headaches. */ | 488 | /* We can't use the standard versions because of RELOC headaches. */ |
@@ -980,7 +1043,7 @@ static void __init prom_instantiate_rtas(void) | |||
980 | 1043 | ||
981 | rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); | 1044 | rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); |
982 | if (!IHANDLE_VALID(rtas_inst)) { | 1045 | if (!IHANDLE_VALID(rtas_inst)) { |
983 | prom_printf("opening rtas package failed"); | 1046 | prom_printf("opening rtas package failed (%x)\n", rtas_inst); |
984 | return; | 1047 | return; |
985 | } | 1048 | } |
986 | 1049 | ||
@@ -988,7 +1051,7 @@ static void __init prom_instantiate_rtas(void) | |||
988 | 1051 | ||
989 | if (call_prom_ret("call-method", 3, 2, &entry, | 1052 | if (call_prom_ret("call-method", 3, 2, &entry, |
990 | ADDR("instantiate-rtas"), | 1053 | ADDR("instantiate-rtas"), |
991 | rtas_inst, base) == PROM_ERROR | 1054 | rtas_inst, base) != 0 |
992 | || entry == 0) { | 1055 | || entry == 0) { |
993 | prom_printf(" failed\n"); | 1056 | prom_printf(" failed\n"); |
994 | return; | 1057 | return; |
@@ -997,8 +1060,10 @@ static void __init prom_instantiate_rtas(void) | |||
997 | 1060 | ||
998 | reserve_mem(base, size); | 1061 | reserve_mem(base, size); |
999 | 1062 | ||
1000 | prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base)); | 1063 | prom_setprop(rtas_node, "/rtas", "linux,rtas-base", |
1001 | prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry)); | 1064 | &base, sizeof(base)); |
1065 | prom_setprop(rtas_node, "/rtas", "linux,rtas-entry", | ||
1066 | &entry, sizeof(entry)); | ||
1002 | 1067 | ||
1003 | prom_debug("rtas base = 0x%x\n", base); | 1068 | prom_debug("rtas base = 0x%x\n", base); |
1004 | prom_debug("rtas entry = 0x%x\n", entry); | 1069 | prom_debug("rtas entry = 0x%x\n", entry); |
@@ -1089,10 +1154,6 @@ static void __init prom_initialize_tce_table(void) | |||
1089 | if (base < local_alloc_bottom) | 1154 | if (base < local_alloc_bottom) |
1090 | local_alloc_bottom = base; | 1155 | local_alloc_bottom = base; |
1091 | 1156 | ||
1092 | /* Save away the TCE table attributes for later use. */ | ||
1093 | prom_setprop(node, "linux,tce-base", &base, sizeof(base)); | ||
1094 | prom_setprop(node, "linux,tce-size", &minsize, sizeof(minsize)); | ||
1095 | |||
1096 | /* It seems OF doesn't null-terminate the path :-( */ | 1157 | /* It seems OF doesn't null-terminate the path :-( */ |
1097 | memset(path, 0, sizeof(path)); | 1158 | memset(path, 0, sizeof(path)); |
1098 | /* Call OF to setup the TCE hardware */ | 1159 | /* Call OF to setup the TCE hardware */ |
@@ -1101,6 +1162,10 @@ static void __init prom_initialize_tce_table(void) | |||
1101 | prom_printf("package-to-path failed\n"); | 1162 | prom_printf("package-to-path failed\n"); |
1102 | } | 1163 | } |
1103 | 1164 | ||
1165 | /* Save away the TCE table attributes for later use. */ | ||
1166 | prom_setprop(node, path, "linux,tce-base", &base, sizeof(base)); | ||
1167 | prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize)); | ||
1168 | |||
1104 | prom_debug("TCE table: %s\n", path); | 1169 | prom_debug("TCE table: %s\n", path); |
1105 | prom_debug("\tnode = 0x%x\n", node); | 1170 | prom_debug("\tnode = 0x%x\n", node); |
1106 | prom_debug("\tbase = 0x%x\n", base); | 1171 | prom_debug("\tbase = 0x%x\n", base); |
@@ -1342,6 +1407,7 @@ static void __init prom_init_client_services(unsigned long pp) | |||
1342 | /* | 1407 | /* |
1343 | * For really old powermacs, we need to map things we claim. | 1408 | * For really old powermacs, we need to map things we claim. |
1344 | * For that, we need the ihandle of the mmu. | 1409 | * For that, we need the ihandle of the mmu. |
1410 | * Also, on the longtrail, we need to work around other bugs. | ||
1345 | */ | 1411 | */ |
1346 | static void __init prom_find_mmu(void) | 1412 | static void __init prom_find_mmu(void) |
1347 | { | 1413 | { |
@@ -1355,12 +1421,19 @@ static void __init prom_find_mmu(void) | |||
1355 | if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0) | 1421 | if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0) |
1356 | return; | 1422 | return; |
1357 | version[sizeof(version) - 1] = 0; | 1423 | version[sizeof(version) - 1] = 0; |
1358 | prom_printf("OF version is '%s'\n", version); | ||
1359 | /* XXX might need to add other versions here */ | 1424 | /* XXX might need to add other versions here */ |
1360 | if (strcmp(version, "Open Firmware, 1.0.5") != 0) | 1425 | if (strcmp(version, "Open Firmware, 1.0.5") == 0) |
1426 | of_workarounds = OF_WA_CLAIM; | ||
1427 | else if (strncmp(version, "FirmWorks,3.", 12) == 0) { | ||
1428 | of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL; | ||
1429 | call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim"); | ||
1430 | } else | ||
1361 | return; | 1431 | return; |
1432 | _prom->memory = call_prom("open", 1, 1, ADDR("/memory")); | ||
1362 | prom_getprop(_prom->chosen, "mmu", &_prom->mmumap, | 1433 | prom_getprop(_prom->chosen, "mmu", &_prom->mmumap, |
1363 | sizeof(_prom->mmumap)); | 1434 | sizeof(_prom->mmumap)); |
1435 | if (!IHANDLE_VALID(_prom->memory) || !IHANDLE_VALID(_prom->mmumap)) | ||
1436 | of_workarounds &= ~OF_WA_CLAIM; /* hmmm */ | ||
1364 | } | 1437 | } |
1365 | #else | 1438 | #else |
1366 | #define prom_find_mmu() | 1439 | #define prom_find_mmu() |
@@ -1382,16 +1455,17 @@ static void __init prom_init_stdout(void) | |||
1382 | memset(path, 0, 256); | 1455 | memset(path, 0, 256); |
1383 | call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255); | 1456 | call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255); |
1384 | val = call_prom("instance-to-package", 1, 1, _prom->stdout); | 1457 | val = call_prom("instance-to-package", 1, 1, _prom->stdout); |
1385 | prom_setprop(_prom->chosen, "linux,stdout-package", &val, sizeof(val)); | 1458 | prom_setprop(_prom->chosen, "/chosen", "linux,stdout-package", |
1459 | &val, sizeof(val)); | ||
1386 | prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device)); | 1460 | prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device)); |
1387 | prom_setprop(_prom->chosen, "linux,stdout-path", | 1461 | prom_setprop(_prom->chosen, "/chosen", "linux,stdout-path", |
1388 | RELOC(of_stdout_device), strlen(RELOC(of_stdout_device))+1); | 1462 | path, strlen(path) + 1); |
1389 | 1463 | ||
1390 | /* If it's a display, note it */ | 1464 | /* If it's a display, note it */ |
1391 | memset(type, 0, sizeof(type)); | 1465 | memset(type, 0, sizeof(type)); |
1392 | prom_getprop(val, "device_type", type, sizeof(type)); | 1466 | prom_getprop(val, "device_type", type, sizeof(type)); |
1393 | if (strcmp(type, RELOC("display")) == 0) | 1467 | if (strcmp(type, RELOC("display")) == 0) |
1394 | prom_setprop(val, "linux,boot-display", NULL, 0); | 1468 | prom_setprop(val, path, "linux,boot-display", NULL, 0); |
1395 | } | 1469 | } |
1396 | 1470 | ||
1397 | static void __init prom_close_stdin(void) | 1471 | static void __init prom_close_stdin(void) |
@@ -1514,7 +1588,7 @@ static void __init prom_check_displays(void) | |||
1514 | 1588 | ||
1515 | /* Success */ | 1589 | /* Success */ |
1516 | prom_printf("done\n"); | 1590 | prom_printf("done\n"); |
1517 | prom_setprop(node, "linux,opened", NULL, 0); | 1591 | prom_setprop(node, path, "linux,opened", NULL, 0); |
1518 | 1592 | ||
1519 | /* Setup a usable color table when the appropriate | 1593 | /* Setup a usable color table when the appropriate |
1520 | * method is available. Should update this to set-colors */ | 1594 | * method is available. Should update this to set-colors */ |
@@ -1884,9 +1958,11 @@ static void __init fixup_device_tree(void) | |||
1884 | /* interrupt on this revision of u3 is number 0 and level */ | 1958 | /* interrupt on this revision of u3 is number 0 and level */ |
1885 | interrupts[0] = 0; | 1959 | interrupts[0] = 0; |
1886 | interrupts[1] = 1; | 1960 | interrupts[1] = 1; |
1887 | prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts)); | 1961 | prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts", |
1962 | &interrupts, sizeof(interrupts)); | ||
1888 | parent = (u32)mpic; | 1963 | parent = (u32)mpic; |
1889 | prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent)); | 1964 | prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent", |
1965 | &parent, sizeof(parent)); | ||
1890 | #endif | 1966 | #endif |
1891 | } | 1967 | } |
1892 | 1968 | ||
@@ -1922,11 +1998,11 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4) | |||
1922 | RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4; | 1998 | RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4; |
1923 | 1999 | ||
1924 | val = RELOC(prom_initrd_start); | 2000 | val = RELOC(prom_initrd_start); |
1925 | prom_setprop(_prom->chosen, "linux,initrd-start", &val, | 2001 | prom_setprop(_prom->chosen, "/chosen", "linux,initrd-start", |
1926 | sizeof(val)); | 2002 | &val, sizeof(val)); |
1927 | val = RELOC(prom_initrd_end); | 2003 | val = RELOC(prom_initrd_end); |
1928 | prom_setprop(_prom->chosen, "linux,initrd-end", &val, | 2004 | prom_setprop(_prom->chosen, "/chosen", "linux,initrd-end", |
1929 | sizeof(val)); | 2005 | &val, sizeof(val)); |
1930 | 2006 | ||
1931 | reserve_mem(RELOC(prom_initrd_start), | 2007 | reserve_mem(RELOC(prom_initrd_start), |
1932 | RELOC(prom_initrd_end) - RELOC(prom_initrd_start)); | 2008 | RELOC(prom_initrd_end) - RELOC(prom_initrd_start)); |
@@ -1969,14 +2045,15 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
1969 | prom_init_client_services(pp); | 2045 | prom_init_client_services(pp); |
1970 | 2046 | ||
1971 | /* | 2047 | /* |
1972 | * Init prom stdout device | 2048 | * See if this OF is old enough that we need to do explicit maps |
2049 | * and other workarounds | ||
1973 | */ | 2050 | */ |
1974 | prom_init_stdout(); | 2051 | prom_find_mmu(); |
1975 | 2052 | ||
1976 | /* | 2053 | /* |
1977 | * See if this OF is old enough that we need to do explicit maps | 2054 | * Init prom stdout device |
1978 | */ | 2055 | */ |
1979 | prom_find_mmu(); | 2056 | prom_init_stdout(); |
1980 | 2057 | ||
1981 | /* | 2058 | /* |
1982 | * Check for an initrd | 2059 | * Check for an initrd |
@@ -1989,14 +2066,15 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
1989 | */ | 2066 | */ |
1990 | RELOC(of_platform) = prom_find_machine_type(); | 2067 | RELOC(of_platform) = prom_find_machine_type(); |
1991 | getprop_rval = RELOC(of_platform); | 2068 | getprop_rval = RELOC(of_platform); |
1992 | prom_setprop(_prom->chosen, "linux,platform", | 2069 | prom_setprop(_prom->chosen, "/chosen", "linux,platform", |
1993 | &getprop_rval, sizeof(getprop_rval)); | 2070 | &getprop_rval, sizeof(getprop_rval)); |
1994 | 2071 | ||
1995 | #ifdef CONFIG_PPC_PSERIES | 2072 | #ifdef CONFIG_PPC_PSERIES |
1996 | /* | 2073 | /* |
1997 | * On pSeries, inform the firmware about our capabilities | 2074 | * On pSeries, inform the firmware about our capabilities |
1998 | */ | 2075 | */ |
1999 | if (RELOC(of_platform) & PLATFORM_PSERIES) | 2076 | if (RELOC(of_platform) == PLATFORM_PSERIES || |
2077 | RELOC(of_platform) == PLATFORM_PSERIES_LPAR) | ||
2000 | prom_send_capabilities(); | 2078 | prom_send_capabilities(); |
2001 | #endif | 2079 | #endif |
2002 | 2080 | ||
@@ -2050,21 +2128,23 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
2050 | * Fill in some infos for use by the kernel later on | 2128 | * Fill in some infos for use by the kernel later on |
2051 | */ | 2129 | */ |
2052 | if (RELOC(prom_memory_limit)) | 2130 | if (RELOC(prom_memory_limit)) |
2053 | prom_setprop(_prom->chosen, "linux,memory-limit", | 2131 | prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit", |
2054 | &RELOC(prom_memory_limit), | 2132 | &RELOC(prom_memory_limit), |
2055 | sizeof(prom_memory_limit)); | 2133 | sizeof(prom_memory_limit)); |
2056 | #ifdef CONFIG_PPC64 | 2134 | #ifdef CONFIG_PPC64 |
2057 | if (RELOC(ppc64_iommu_off)) | 2135 | if (RELOC(ppc64_iommu_off)) |
2058 | prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0); | 2136 | prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off", |
2137 | NULL, 0); | ||
2059 | 2138 | ||
2060 | if (RELOC(iommu_force_on)) | 2139 | if (RELOC(iommu_force_on)) |
2061 | prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0); | 2140 | prom_setprop(_prom->chosen, "/chosen", "linux,iommu-force-on", |
2141 | NULL, 0); | ||
2062 | 2142 | ||
2063 | if (RELOC(prom_tce_alloc_start)) { | 2143 | if (RELOC(prom_tce_alloc_start)) { |
2064 | prom_setprop(_prom->chosen, "linux,tce-alloc-start", | 2144 | prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-start", |
2065 | &RELOC(prom_tce_alloc_start), | 2145 | &RELOC(prom_tce_alloc_start), |
2066 | sizeof(prom_tce_alloc_start)); | 2146 | sizeof(prom_tce_alloc_start)); |
2067 | prom_setprop(_prom->chosen, "linux,tce-alloc-end", | 2147 | prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-end", |
2068 | &RELOC(prom_tce_alloc_end), | 2148 | &RELOC(prom_tce_alloc_end), |
2069 | sizeof(prom_tce_alloc_end)); | 2149 | sizeof(prom_tce_alloc_end)); |
2070 | } | 2150 | } |
@@ -2081,8 +2161,13 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
2081 | prom_printf("copying OF device tree ...\n"); | 2161 | prom_printf("copying OF device tree ...\n"); |
2082 | flatten_device_tree(); | 2162 | flatten_device_tree(); |
2083 | 2163 | ||
2084 | /* in case stdin is USB and still active on IBM machines... */ | 2164 | /* |
2085 | prom_close_stdin(); | 2165 | * in case stdin is USB and still active on IBM machines... |
2166 | * Unfortunately quiesce crashes on some powermacs if we have | ||
2167 | * closed stdin already (in particular the powerbook 101). | ||
2168 | */ | ||
2169 | if (RELOC(of_platform) != PLATFORM_POWERMAC) | ||
2170 | prom_close_stdin(); | ||
2086 | 2171 | ||
2087 | /* | 2172 | /* |
2088 | * Call OF "quiesce" method to shut down pending DMA's from | 2173 | * Call OF "quiesce" method to shut down pending DMA's from |
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index 5bdd5b079d96..ae1a36449ccd 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c | |||
@@ -259,7 +259,7 @@ static int __init proc_rtas_init(void) | |||
259 | { | 259 | { |
260 | struct proc_dir_entry *entry; | 260 | struct proc_dir_entry *entry; |
261 | 261 | ||
262 | if (!(systemcfg->platform & PLATFORM_PSERIES)) | 262 | if (_machine != PLATFORM_PSERIES && _machine != PLATFORM_PSERIES_LPAR) |
263 | return 1; | 263 | return 1; |
264 | 264 | ||
265 | rtas_node = of_find_node_by_name(NULL, "rtas"); | 265 | rtas_node = of_find_node_by_name(NULL, "rtas"); |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 9d4e07f6f1ec..4283fa33f784 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -29,9 +29,6 @@ | |||
29 | #include <asm/delay.h> | 29 | #include <asm/delay.h> |
30 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
31 | #include <asm/lmb.h> | 31 | #include <asm/lmb.h> |
32 | #ifdef CONFIG_PPC64 | ||
33 | #include <asm/systemcfg.h> | ||
34 | #endif | ||
35 | 32 | ||
36 | struct rtas_t rtas = { | 33 | struct rtas_t rtas = { |
37 | .lock = SPIN_LOCK_UNLOCKED | 34 | .lock = SPIN_LOCK_UNLOCKED |
@@ -671,7 +668,7 @@ void __init rtas_initialize(void) | |||
671 | * the stop-self token if any | 668 | * the stop-self token if any |
672 | */ | 669 | */ |
673 | #ifdef CONFIG_PPC64 | 670 | #ifdef CONFIG_PPC64 |
674 | if (systemcfg->platform == PLATFORM_PSERIES_LPAR) | 671 | if (_machine == PLATFORM_PSERIES_LPAR) |
675 | rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX); | 672 | rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX); |
676 | #endif | 673 | #endif |
677 | rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region); | 674 | rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region); |
diff --git a/arch/ppc64/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 3c3f19192fcc..0e5a8e116653 100644 --- a/arch/ppc64/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c | |||
@@ -5,19 +5,19 @@ | |||
5 | * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM | 5 | * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM |
6 | * | 6 | * |
7 | * RTAS specific routines for PCI. | 7 | * RTAS specific routines for PCI. |
8 | * | 8 | * |
9 | * Based on code from pci.c, chrp_pci.c and pSeries_pci.c | 9 | * Based on code from pci.c, chrp_pci.c and pSeries_pci.c |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
13 | * the Free Software Foundation; either version 2 of the License, or | 13 | * the Free Software Foundation; either version 2 of the License, or |
14 | * (at your option) any later version. | 14 | * (at your option) any later version. |
15 | * | 15 | * |
16 | * This program is distributed in the hope that it will be useful, | 16 | * This program is distributed in the hope that it will be useful, |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 | * GNU General Public License for more details. | 19 | * GNU General Public License for more details. |
20 | * | 20 | * |
21 | * You should have received a copy of the GNU General Public License | 21 | * You should have received a copy of the GNU General Public License |
22 | * along with this program; if not, write to the Free Software | 22 | * along with this program; if not, write to the Free Software |
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
@@ -47,7 +47,7 @@ static int write_pci_config; | |||
47 | static int ibm_read_pci_config; | 47 | static int ibm_read_pci_config; |
48 | static int ibm_write_pci_config; | 48 | static int ibm_write_pci_config; |
49 | 49 | ||
50 | static int config_access_valid(struct pci_dn *dn, int where) | 50 | static inline int config_access_valid(struct pci_dn *dn, int where) |
51 | { | 51 | { |
52 | if (where < 256) | 52 | if (where < 256) |
53 | return 1; | 53 | return 1; |
@@ -72,16 +72,14 @@ static int of_device_available(struct device_node * dn) | |||
72 | return 0; | 72 | return 0; |
73 | } | 73 | } |
74 | 74 | ||
75 | static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val) | 75 | static int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val) |
76 | { | 76 | { |
77 | int returnval = -1; | 77 | int returnval = -1; |
78 | unsigned long buid, addr; | 78 | unsigned long buid, addr; |
79 | int ret; | 79 | int ret; |
80 | struct pci_dn *pdn; | ||
81 | 80 | ||
82 | if (!dn || !dn->data) | 81 | if (!pdn) |
83 | return PCIBIOS_DEVICE_NOT_FOUND; | 82 | return PCIBIOS_DEVICE_NOT_FOUND; |
84 | pdn = dn->data; | ||
85 | if (!config_access_valid(pdn, where)) | 83 | if (!config_access_valid(pdn, where)) |
86 | return PCIBIOS_BAD_REGISTER_NUMBER; | 84 | return PCIBIOS_BAD_REGISTER_NUMBER; |
87 | 85 | ||
@@ -90,7 +88,7 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va | |||
90 | buid = pdn->phb->buid; | 88 | buid = pdn->phb->buid; |
91 | if (buid) { | 89 | if (buid) { |
92 | ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval, | 90 | ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval, |
93 | addr, buid >> 32, buid & 0xffffffff, size); | 91 | addr, BUID_HI(buid), BUID_LO(buid), size); |
94 | } else { | 92 | } else { |
95 | ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size); | 93 | ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size); |
96 | } | 94 | } |
@@ -100,7 +98,7 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va | |||
100 | return PCIBIOS_DEVICE_NOT_FOUND; | 98 | return PCIBIOS_DEVICE_NOT_FOUND; |
101 | 99 | ||
102 | if (returnval == EEH_IO_ERROR_VALUE(size) && | 100 | if (returnval == EEH_IO_ERROR_VALUE(size) && |
103 | eeh_dn_check_failure (dn, NULL)) | 101 | eeh_dn_check_failure (pdn->node, NULL)) |
104 | return PCIBIOS_DEVICE_NOT_FOUND; | 102 | return PCIBIOS_DEVICE_NOT_FOUND; |
105 | 103 | ||
106 | return PCIBIOS_SUCCESSFUL; | 104 | return PCIBIOS_SUCCESSFUL; |
@@ -118,23 +116,23 @@ static int rtas_pci_read_config(struct pci_bus *bus, | |||
118 | busdn = bus->sysdata; /* must be a phb */ | 116 | busdn = bus->sysdata; /* must be a phb */ |
119 | 117 | ||
120 | /* Search only direct children of the bus */ | 118 | /* Search only direct children of the bus */ |
121 | for (dn = busdn->child; dn; dn = dn->sibling) | 119 | for (dn = busdn->child; dn; dn = dn->sibling) { |
122 | if (dn->data && PCI_DN(dn)->devfn == devfn | 120 | struct pci_dn *pdn = PCI_DN(dn); |
121 | if (pdn && pdn->devfn == devfn | ||
123 | && of_device_available(dn)) | 122 | && of_device_available(dn)) |
124 | return rtas_read_config(dn, where, size, val); | 123 | return rtas_read_config(pdn, where, size, val); |
124 | } | ||
125 | 125 | ||
126 | return PCIBIOS_DEVICE_NOT_FOUND; | 126 | return PCIBIOS_DEVICE_NOT_FOUND; |
127 | } | 127 | } |
128 | 128 | ||
129 | int rtas_write_config(struct device_node *dn, int where, int size, u32 val) | 129 | int rtas_write_config(struct pci_dn *pdn, int where, int size, u32 val) |
130 | { | 130 | { |
131 | unsigned long buid, addr; | 131 | unsigned long buid, addr; |
132 | int ret; | 132 | int ret; |
133 | struct pci_dn *pdn; | ||
134 | 133 | ||
135 | if (!dn || !dn->data) | 134 | if (!pdn) |
136 | return PCIBIOS_DEVICE_NOT_FOUND; | 135 | return PCIBIOS_DEVICE_NOT_FOUND; |
137 | pdn = dn->data; | ||
138 | if (!config_access_valid(pdn, where)) | 136 | if (!config_access_valid(pdn, where)) |
139 | return PCIBIOS_BAD_REGISTER_NUMBER; | 137 | return PCIBIOS_BAD_REGISTER_NUMBER; |
140 | 138 | ||
@@ -142,7 +140,8 @@ int rtas_write_config(struct device_node *dn, int where, int size, u32 val) | |||
142 | (pdn->devfn << 8) | (where & 0xff); | 140 | (pdn->devfn << 8) | (where & 0xff); |
143 | buid = pdn->phb->buid; | 141 | buid = pdn->phb->buid; |
144 | if (buid) { | 142 | if (buid) { |
145 | ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val); | 143 | ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, |
144 | BUID_HI(buid), BUID_LO(buid), size, (ulong) val); | ||
146 | } else { | 145 | } else { |
147 | ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val); | 146 | ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val); |
148 | } | 147 | } |
@@ -165,10 +164,12 @@ static int rtas_pci_write_config(struct pci_bus *bus, | |||
165 | busdn = bus->sysdata; /* must be a phb */ | 164 | busdn = bus->sysdata; /* must be a phb */ |
166 | 165 | ||
167 | /* Search only direct children of the bus */ | 166 | /* Search only direct children of the bus */ |
168 | for (dn = busdn->child; dn; dn = dn->sibling) | 167 | for (dn = busdn->child; dn; dn = dn->sibling) { |
169 | if (dn->data && PCI_DN(dn)->devfn == devfn | 168 | struct pci_dn *pdn = PCI_DN(dn); |
169 | if (pdn && pdn->devfn == devfn | ||
170 | && of_device_available(dn)) | 170 | && of_device_available(dn)) |
171 | return rtas_write_config(dn, where, size, val); | 171 | return rtas_write_config(pdn, where, size, val); |
172 | } | ||
172 | return PCIBIOS_DEVICE_NOT_FOUND; | 173 | return PCIBIOS_DEVICE_NOT_FOUND; |
173 | } | 174 | } |
174 | 175 | ||
@@ -221,7 +222,7 @@ static void python_countermeasures(struct device_node *dev, | |||
221 | /* Python's register file is 1 MB in size. */ | 222 | /* Python's register file is 1 MB in size. */ |
222 | chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), 0x100000); | 223 | chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), 0x100000); |
223 | 224 | ||
224 | /* | 225 | /* |
225 | * Firmware doesn't always clear this bit which is critical | 226 | * Firmware doesn't always clear this bit which is critical |
226 | * for good performance - Anton | 227 | * for good performance - Anton |
227 | */ | 228 | */ |
@@ -292,7 +293,7 @@ static int phb_set_bus_ranges(struct device_node *dev, | |||
292 | if (bus_range == NULL || len < 2 * sizeof(int)) { | 293 | if (bus_range == NULL || len < 2 * sizeof(int)) { |
293 | return 1; | 294 | return 1; |
294 | } | 295 | } |
295 | 296 | ||
296 | phb->first_busno = bus_range[0]; | 297 | phb->first_busno = bus_range[0]; |
297 | phb->last_busno = bus_range[1]; | 298 | phb->last_busno = bus_range[1]; |
298 | 299 | ||
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index e22856ecb5a0..bae4bff138f1 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <asm/io.h> | 33 | #include <asm/io.h> |
34 | #include <asm/prom.h> | 34 | #include <asm/prom.h> |
35 | #include <asm/processor.h> | 35 | #include <asm/processor.h> |
36 | #include <asm/systemcfg.h> | ||
36 | #include <asm/pgtable.h> | 37 | #include <asm/pgtable.h> |
37 | #include <asm/smp.h> | 38 | #include <asm/smp.h> |
38 | #include <asm/elf.h> | 39 | #include <asm/elf.h> |
@@ -51,6 +52,9 @@ | |||
51 | #include <asm/page.h> | 52 | #include <asm/page.h> |
52 | #include <asm/mmu.h> | 53 | #include <asm/mmu.h> |
53 | #include <asm/lmb.h> | 54 | #include <asm/lmb.h> |
55 | #include <asm/xmon.h> | ||
56 | |||
57 | #include "setup.h" | ||
54 | 58 | ||
55 | #undef DEBUG | 59 | #undef DEBUG |
56 | 60 | ||
@@ -60,6 +64,13 @@ | |||
60 | #define DBG(fmt...) | 64 | #define DBG(fmt...) |
61 | #endif | 65 | #endif |
62 | 66 | ||
67 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
68 | int _machine = 0; | ||
69 | EXPORT_SYMBOL(_machine); | ||
70 | #endif | ||
71 | |||
72 | unsigned long klimit = (unsigned long) _end; | ||
73 | |||
63 | /* | 74 | /* |
64 | * This still seems to be needed... -- paulus | 75 | * This still seems to be needed... -- paulus |
65 | */ | 76 | */ |
@@ -510,8 +521,8 @@ void __init smp_setup_cpu_maps(void) | |||
510 | * On pSeries LPAR, we need to know how many cpus | 521 | * On pSeries LPAR, we need to know how many cpus |
511 | * could possibly be added to this partition. | 522 | * could possibly be added to this partition. |
512 | */ | 523 | */ |
513 | if (systemcfg->platform == PLATFORM_PSERIES_LPAR && | 524 | if (_machine == PLATFORM_PSERIES_LPAR && |
514 | (dn = of_find_node_by_path("/rtas"))) { | 525 | (dn = of_find_node_by_path("/rtas"))) { |
515 | int num_addr_cell, num_size_cell, maxcpus; | 526 | int num_addr_cell, num_size_cell, maxcpus; |
516 | unsigned int *ireg; | 527 | unsigned int *ireg; |
517 | 528 | ||
@@ -555,7 +566,27 @@ void __init smp_setup_cpu_maps(void) | |||
555 | cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); | 566 | cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); |
556 | } | 567 | } |
557 | 568 | ||
558 | systemcfg->processorCount = num_present_cpus(); | 569 | _systemcfg->processorCount = num_present_cpus(); |
559 | #endif /* CONFIG_PPC64 */ | 570 | #endif /* CONFIG_PPC64 */ |
560 | } | 571 | } |
561 | #endif /* CONFIG_SMP */ | 572 | #endif /* CONFIG_SMP */ |
573 | |||
574 | #ifdef CONFIG_XMON | ||
575 | static int __init early_xmon(char *p) | ||
576 | { | ||
577 | /* ensure xmon is enabled */ | ||
578 | if (p) { | ||
579 | if (strncmp(p, "on", 2) == 0) | ||
580 | xmon_init(1); | ||
581 | if (strncmp(p, "off", 3) == 0) | ||
582 | xmon_init(0); | ||
583 | if (strncmp(p, "early", 5) != 0) | ||
584 | return 0; | ||
585 | } | ||
586 | xmon_init(1); | ||
587 | debugger(NULL); | ||
588 | |||
589 | return 0; | ||
590 | } | ||
591 | early_param("xmon", early_xmon); | ||
592 | #endif | ||
diff --git a/arch/powerpc/kernel/setup.h b/arch/powerpc/kernel/setup.h new file mode 100644 index 000000000000..2ebba755272e --- /dev/null +++ b/arch/powerpc/kernel/setup.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _POWERPC_KERNEL_SETUP_H | ||
2 | #define _POWERPC_KERNEL_SETUP_H | ||
3 | |||
4 | void check_for_initrd(void); | ||
5 | |||
6 | #endif /* _POWERPC_KERNEL_SETUP_H */ | ||
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 3af2631e3fab..c98cfcc9cd9a 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -40,6 +40,8 @@ | |||
40 | #include <asm/xmon.h> | 40 | #include <asm/xmon.h> |
41 | #include <asm/time.h> | 41 | #include <asm/time.h> |
42 | 42 | ||
43 | #include "setup.h" | ||
44 | |||
43 | #define DBG(fmt...) | 45 | #define DBG(fmt...) |
44 | 46 | ||
45 | #if defined CONFIG_KGDB | 47 | #if defined CONFIG_KGDB |
@@ -70,8 +72,6 @@ unsigned int DMA_MODE_WRITE; | |||
70 | int have_of = 1; | 72 | int have_of = 1; |
71 | 73 | ||
72 | #ifdef CONFIG_PPC_MULTIPLATFORM | 74 | #ifdef CONFIG_PPC_MULTIPLATFORM |
73 | int _machine = 0; | ||
74 | |||
75 | extern void prep_init(void); | 75 | extern void prep_init(void); |
76 | extern void pmac_init(void); | 76 | extern void pmac_init(void); |
77 | extern void chrp_init(void); | 77 | extern void chrp_init(void); |
@@ -279,7 +279,6 @@ arch_initcall(ppc_init); | |||
279 | /* Warning, IO base is not yet inited */ | 279 | /* Warning, IO base is not yet inited */ |
280 | void __init setup_arch(char **cmdline_p) | 280 | void __init setup_arch(char **cmdline_p) |
281 | { | 281 | { |
282 | extern char *klimit; | ||
283 | extern void do_init_bootmem(void); | 282 | extern void do_init_bootmem(void); |
284 | 283 | ||
285 | /* so udelay does something sensible, assume <= 1000 bogomips */ | 284 | /* so udelay does something sensible, assume <= 1000 bogomips */ |
@@ -303,14 +302,9 @@ void __init setup_arch(char **cmdline_p) | |||
303 | pmac_feature_init(); /* New cool way */ | 302 | pmac_feature_init(); /* New cool way */ |
304 | #endif | 303 | #endif |
305 | 304 | ||
306 | #ifdef CONFIG_XMON | 305 | #ifdef CONFIG_XMON_DEFAULT |
307 | xmon_map_scc(); | 306 | xmon_init(1); |
308 | if (strstr(cmd_line, "xmon")) { | 307 | #endif |
309 | xmon_init(1); | ||
310 | debugger(NULL); | ||
311 | } | ||
312 | #endif /* CONFIG_XMON */ | ||
313 | if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab); | ||
314 | 308 | ||
315 | #if defined(CONFIG_KGDB) | 309 | #if defined(CONFIG_KGDB) |
316 | if (ppc_md.kgdb_map_scc) | 310 | if (ppc_md.kgdb_map_scc) |
@@ -343,7 +337,7 @@ void __init setup_arch(char **cmdline_p) | |||
343 | init_mm.start_code = PAGE_OFFSET; | 337 | init_mm.start_code = PAGE_OFFSET; |
344 | init_mm.end_code = (unsigned long) _etext; | 338 | init_mm.end_code = (unsigned long) _etext; |
345 | init_mm.end_data = (unsigned long) _edata; | 339 | init_mm.end_data = (unsigned long) _edata; |
346 | init_mm.brk = (unsigned long) klimit; | 340 | init_mm.brk = klimit; |
347 | 341 | ||
348 | /* Save unparsed command line copy for /proc/cmdline */ | 342 | /* Save unparsed command line copy for /proc/cmdline */ |
349 | strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); | 343 | strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 0471e843b6c5..6791668213e7 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -61,6 +61,8 @@ | |||
61 | #include <asm/xmon.h> | 61 | #include <asm/xmon.h> |
62 | #include <asm/udbg.h> | 62 | #include <asm/udbg.h> |
63 | 63 | ||
64 | #include "setup.h" | ||
65 | |||
64 | #ifdef DEBUG | 66 | #ifdef DEBUG |
65 | #define DBG(fmt...) udbg_printf(fmt) | 67 | #define DBG(fmt...) udbg_printf(fmt) |
66 | #else | 68 | #else |
@@ -94,15 +96,6 @@ extern void udbg_init_maple_realmode(void); | |||
94 | do { udbg_putc = call_rtas_display_status_delay; } while(0) | 96 | do { udbg_putc = call_rtas_display_status_delay; } while(0) |
95 | #endif | 97 | #endif |
96 | 98 | ||
97 | /* extern void *stab; */ | ||
98 | extern unsigned long klimit; | ||
99 | |||
100 | extern void mm_init_ppc64(void); | ||
101 | extern void stab_initialize(unsigned long stab); | ||
102 | extern void htab_initialize(void); | ||
103 | extern void early_init_devtree(void *flat_dt); | ||
104 | extern void unflatten_device_tree(void); | ||
105 | |||
106 | int have_of = 1; | 99 | int have_of = 1; |
107 | int boot_cpuid = 0; | 100 | int boot_cpuid = 0; |
108 | int boot_cpuid_phys = 0; | 101 | int boot_cpuid_phys = 0; |
@@ -254,11 +247,10 @@ void __init early_setup(unsigned long dt_ptr) | |||
254 | * Iterate all ppc_md structures until we find the proper | 247 | * Iterate all ppc_md structures until we find the proper |
255 | * one for the current machine type | 248 | * one for the current machine type |
256 | */ | 249 | */ |
257 | DBG("Probing machine type for platform %x...\n", | 250 | DBG("Probing machine type for platform %x...\n", _machine); |
258 | systemcfg->platform); | ||
259 | 251 | ||
260 | for (mach = machines; *mach; mach++) { | 252 | for (mach = machines; *mach; mach++) { |
261 | if ((*mach)->probe(systemcfg->platform)) | 253 | if ((*mach)->probe(_machine)) |
262 | break; | 254 | break; |
263 | } | 255 | } |
264 | /* What can we do if we didn't find ? */ | 256 | /* What can we do if we didn't find ? */ |
@@ -290,6 +282,28 @@ void __init early_setup(unsigned long dt_ptr) | |||
290 | DBG(" <- early_setup()\n"); | 282 | DBG(" <- early_setup()\n"); |
291 | } | 283 | } |
292 | 284 | ||
285 | #ifdef CONFIG_SMP | ||
286 | void early_setup_secondary(void) | ||
287 | { | ||
288 | struct paca_struct *lpaca = get_paca(); | ||
289 | |||
290 | /* Mark enabled in PACA */ | ||
291 | lpaca->proc_enabled = 0; | ||
292 | |||
293 | /* Initialize hash table for that CPU */ | ||
294 | htab_initialize_secondary(); | ||
295 | |||
296 | /* Initialize STAB/SLB. We use a virtual address as it works | ||
297 | * in real mode on pSeries and we want a virutal address on | ||
298 | * iSeries anyway | ||
299 | */ | ||
300 | if (cpu_has_feature(CPU_FTR_SLB)) | ||
301 | slb_initialize(); | ||
302 | else | ||
303 | stab_initialize(lpaca->stab_addr); | ||
304 | } | ||
305 | |||
306 | #endif /* CONFIG_SMP */ | ||
293 | 307 | ||
294 | #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC) | 308 | #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC) |
295 | void smp_release_cpus(void) | 309 | void smp_release_cpus(void) |
@@ -315,7 +329,8 @@ void smp_release_cpus(void) | |||
315 | #endif /* CONFIG_SMP || CONFIG_KEXEC */ | 329 | #endif /* CONFIG_SMP || CONFIG_KEXEC */ |
316 | 330 | ||
317 | /* | 331 | /* |
318 | * Initialize some remaining members of the ppc64_caches and systemcfg structures | 332 | * Initialize some remaining members of the ppc64_caches and systemcfg |
333 | * structures | ||
319 | * (at least until we get rid of them completely). This is mostly some | 334 | * (at least until we get rid of them completely). This is mostly some |
320 | * cache informations about the CPU that will be used by cache flush | 335 | * cache informations about the CPU that will be used by cache flush |
321 | * routines and/or provided to userland | 336 | * routines and/or provided to userland |
@@ -340,7 +355,7 @@ static void __init initialize_cache_info(void) | |||
340 | const char *dc, *ic; | 355 | const char *dc, *ic; |
341 | 356 | ||
342 | /* Then read cache informations */ | 357 | /* Then read cache informations */ |
343 | if (systemcfg->platform == PLATFORM_POWERMAC) { | 358 | if (_machine == PLATFORM_POWERMAC) { |
344 | dc = "d-cache-block-size"; | 359 | dc = "d-cache-block-size"; |
345 | ic = "i-cache-block-size"; | 360 | ic = "i-cache-block-size"; |
346 | } else { | 361 | } else { |
@@ -360,8 +375,8 @@ static void __init initialize_cache_info(void) | |||
360 | DBG("Argh, can't find dcache properties ! " | 375 | DBG("Argh, can't find dcache properties ! " |
361 | "sizep: %p, lsizep: %p\n", sizep, lsizep); | 376 | "sizep: %p, lsizep: %p\n", sizep, lsizep); |
362 | 377 | ||
363 | systemcfg->dcache_size = ppc64_caches.dsize = size; | 378 | _systemcfg->dcache_size = ppc64_caches.dsize = size; |
364 | systemcfg->dcache_line_size = | 379 | _systemcfg->dcache_line_size = |
365 | ppc64_caches.dline_size = lsize; | 380 | ppc64_caches.dline_size = lsize; |
366 | ppc64_caches.log_dline_size = __ilog2(lsize); | 381 | ppc64_caches.log_dline_size = __ilog2(lsize); |
367 | ppc64_caches.dlines_per_page = PAGE_SIZE / lsize; | 382 | ppc64_caches.dlines_per_page = PAGE_SIZE / lsize; |
@@ -378,8 +393,8 @@ static void __init initialize_cache_info(void) | |||
378 | DBG("Argh, can't find icache properties ! " | 393 | DBG("Argh, can't find icache properties ! " |
379 | "sizep: %p, lsizep: %p\n", sizep, lsizep); | 394 | "sizep: %p, lsizep: %p\n", sizep, lsizep); |
380 | 395 | ||
381 | systemcfg->icache_size = ppc64_caches.isize = size; | 396 | _systemcfg->icache_size = ppc64_caches.isize = size; |
382 | systemcfg->icache_line_size = | 397 | _systemcfg->icache_line_size = |
383 | ppc64_caches.iline_size = lsize; | 398 | ppc64_caches.iline_size = lsize; |
384 | ppc64_caches.log_iline_size = __ilog2(lsize); | 399 | ppc64_caches.log_iline_size = __ilog2(lsize); |
385 | ppc64_caches.ilines_per_page = PAGE_SIZE / lsize; | 400 | ppc64_caches.ilines_per_page = PAGE_SIZE / lsize; |
@@ -387,10 +402,12 @@ static void __init initialize_cache_info(void) | |||
387 | } | 402 | } |
388 | 403 | ||
389 | /* Add an eye catcher and the systemcfg layout version number */ | 404 | /* Add an eye catcher and the systemcfg layout version number */ |
390 | strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64"); | 405 | strcpy(_systemcfg->eye_catcher, "SYSTEMCFG:PPC64"); |
391 | systemcfg->version.major = SYSTEMCFG_MAJOR; | 406 | _systemcfg->version.major = SYSTEMCFG_MAJOR; |
392 | systemcfg->version.minor = SYSTEMCFG_MINOR; | 407 | _systemcfg->version.minor = SYSTEMCFG_MINOR; |
393 | systemcfg->processor = mfspr(SPRN_PVR); | 408 | _systemcfg->processor = mfspr(SPRN_PVR); |
409 | _systemcfg->platform = _machine; | ||
410 | _systemcfg->physicalMemorySize = lmb_phys_mem_size(); | ||
394 | 411 | ||
395 | DBG(" <- initialize_cache_info()\n"); | 412 | DBG(" <- initialize_cache_info()\n"); |
396 | } | 413 | } |
@@ -479,10 +496,10 @@ void __init setup_system(void) | |||
479 | printk("-----------------------------------------------------\n"); | 496 | printk("-----------------------------------------------------\n"); |
480 | printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size); | 497 | printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size); |
481 | printk("ppc64_interrupt_controller = 0x%ld\n", ppc64_interrupt_controller); | 498 | printk("ppc64_interrupt_controller = 0x%ld\n", ppc64_interrupt_controller); |
482 | printk("systemcfg = 0x%p\n", systemcfg); | 499 | printk("systemcfg = 0x%p\n", _systemcfg); |
483 | printk("systemcfg->platform = 0x%x\n", systemcfg->platform); | 500 | printk("systemcfg->platform = 0x%x\n", _systemcfg->platform); |
484 | printk("systemcfg->processorCount = 0x%lx\n", systemcfg->processorCount); | 501 | printk("systemcfg->processorCount = 0x%lx\n", _systemcfg->processorCount); |
485 | printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize); | 502 | printk("systemcfg->physicalMemorySize = 0x%lx\n", _systemcfg->physicalMemorySize); |
486 | printk("ppc64_caches.dcache_line_size = 0x%x\n", | 503 | printk("ppc64_caches.dcache_line_size = 0x%x\n", |
487 | ppc64_caches.dline_size); | 504 | ppc64_caches.dline_size); |
488 | printk("ppc64_caches.icache_line_size = 0x%x\n", | 505 | printk("ppc64_caches.icache_line_size = 0x%x\n", |
@@ -564,12 +581,12 @@ void __init setup_syscall_map(void) | |||
564 | for (i = 0; i < __NR_syscalls; i++) { | 581 | for (i = 0; i < __NR_syscalls; i++) { |
565 | if (sys_call_table[i*2] != sys_ni_syscall) { | 582 | if (sys_call_table[i*2] != sys_ni_syscall) { |
566 | count64++; | 583 | count64++; |
567 | systemcfg->syscall_map_64[i >> 5] |= | 584 | _systemcfg->syscall_map_64[i >> 5] |= |
568 | 0x80000000UL >> (i & 0x1f); | 585 | 0x80000000UL >> (i & 0x1f); |
569 | } | 586 | } |
570 | if (sys_call_table[i*2+1] != sys_ni_syscall) { | 587 | if (sys_call_table[i*2+1] != sys_ni_syscall) { |
571 | count32++; | 588 | count32++; |
572 | systemcfg->syscall_map_32[i >> 5] |= | 589 | _systemcfg->syscall_map_32[i >> 5] |= |
573 | 0x80000000UL >> (i & 0x1f); | 590 | 0x80000000UL >> (i & 0x1f); |
574 | } | 591 | } |
575 | } | 592 | } |
@@ -858,26 +875,6 @@ int check_legacy_ioport(unsigned long base_port) | |||
858 | } | 875 | } |
859 | EXPORT_SYMBOL(check_legacy_ioport); | 876 | EXPORT_SYMBOL(check_legacy_ioport); |
860 | 877 | ||
861 | #ifdef CONFIG_XMON | ||
862 | static int __init early_xmon(char *p) | ||
863 | { | ||
864 | /* ensure xmon is enabled */ | ||
865 | if (p) { | ||
866 | if (strncmp(p, "on", 2) == 0) | ||
867 | xmon_init(1); | ||
868 | if (strncmp(p, "off", 3) == 0) | ||
869 | xmon_init(0); | ||
870 | if (strncmp(p, "early", 5) != 0) | ||
871 | return 0; | ||
872 | } | ||
873 | xmon_init(1); | ||
874 | debugger(NULL); | ||
875 | |||
876 | return 0; | ||
877 | } | ||
878 | early_param("xmon", early_xmon); | ||
879 | #endif | ||
880 | |||
881 | void cpu_die(void) | 878 | void cpu_die(void) |
882 | { | 879 | { |
883 | if (ppc_md.cpu_die) | 880 | if (ppc_md.cpu_die) |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 081d931eae48..a7c4515f320f 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -42,6 +42,7 @@ | |||
42 | 42 | ||
43 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
44 | #include <asm/cacheflush.h> | 44 | #include <asm/cacheflush.h> |
45 | #include <asm/sigcontext.h> | ||
45 | #ifdef CONFIG_PPC64 | 46 | #ifdef CONFIG_PPC64 |
46 | #include "ppc32.h" | 47 | #include "ppc32.h" |
47 | #include <asm/unistd.h> | 48 | #include <asm/unistd.h> |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 36d67a8d7cbb..e28a139c29d0 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <asm/cputable.h> | 44 | #include <asm/cputable.h> |
45 | #include <asm/system.h> | 45 | #include <asm/system.h> |
46 | #include <asm/mpic.h> | 46 | #include <asm/mpic.h> |
47 | #include <asm/systemcfg.h> | ||
47 | #ifdef CONFIG_PPC64 | 48 | #ifdef CONFIG_PPC64 |
48 | #include <asm/paca.h> | 49 | #include <asm/paca.h> |
49 | #endif | 50 | #endif |
@@ -368,9 +369,11 @@ int generic_cpu_disable(void) | |||
368 | if (cpu == boot_cpuid) | 369 | if (cpu == boot_cpuid) |
369 | return -EBUSY; | 370 | return -EBUSY; |
370 | 371 | ||
371 | systemcfg->processorCount--; | ||
372 | cpu_clear(cpu, cpu_online_map); | 372 | cpu_clear(cpu, cpu_online_map); |
373 | #ifdef CONFIG_PPC64 | ||
374 | _systemcfg->processorCount--; | ||
373 | fixup_irqs(cpu_online_map); | 375 | fixup_irqs(cpu_online_map); |
376 | #endif | ||
374 | return 0; | 377 | return 0; |
375 | } | 378 | } |
376 | 379 | ||
@@ -388,9 +391,11 @@ int generic_cpu_enable(unsigned int cpu) | |||
388 | while (!cpu_online(cpu)) | 391 | while (!cpu_online(cpu)) |
389 | cpu_relax(); | 392 | cpu_relax(); |
390 | 393 | ||
394 | #ifdef CONFIG_PPC64 | ||
391 | fixup_irqs(cpu_online_map); | 395 | fixup_irqs(cpu_online_map); |
392 | /* counter the irq disable in fixup_irqs */ | 396 | /* counter the irq disable in fixup_irqs */ |
393 | local_irq_enable(); | 397 | local_irq_enable(); |
398 | #endif | ||
394 | return 0; | 399 | return 0; |
395 | } | 400 | } |
396 | 401 | ||
@@ -419,7 +424,9 @@ void generic_mach_cpu_die(void) | |||
419 | while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE) | 424 | while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE) |
420 | cpu_relax(); | 425 | cpu_relax(); |
421 | 426 | ||
427 | #ifdef CONFIG_PPC64 | ||
422 | flush_tlb_pending(); | 428 | flush_tlb_pending(); |
429 | #endif | ||
423 | cpu_set(cpu, cpu_online_map); | 430 | cpu_set(cpu, cpu_online_map); |
424 | local_irq_enable(); | 431 | local_irq_enable(); |
425 | } | 432 | } |
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index a8210ed5c686..9c921d1c4084 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c | |||
@@ -52,7 +52,6 @@ | |||
52 | #include <asm/semaphore.h> | 52 | #include <asm/semaphore.h> |
53 | #include <asm/time.h> | 53 | #include <asm/time.h> |
54 | #include <asm/mmu_context.h> | 54 | #include <asm/mmu_context.h> |
55 | #include <asm/systemcfg.h> | ||
56 | #include <asm/ppc-pci.h> | 55 | #include <asm/ppc-pci.h> |
57 | 56 | ||
58 | /* readdir & getdents */ | 57 | /* readdir & getdents */ |
diff --git a/arch/ppc64/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index e99ec62c2c52..850af198fb5f 100644 --- a/arch/ppc64/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
@@ -232,7 +232,7 @@ static void register_cpu_online(unsigned int cpu) | |||
232 | sysdev_create_file(s, &attr_pmc7); | 232 | sysdev_create_file(s, &attr_pmc7); |
233 | if (cur_cpu_spec->num_pmcs >= 8) | 233 | if (cur_cpu_spec->num_pmcs >= 8) |
234 | sysdev_create_file(s, &attr_pmc8); | 234 | sysdev_create_file(s, &attr_pmc8); |
235 | 235 | ||
236 | if (cpu_has_feature(CPU_FTR_SMT)) | 236 | if (cpu_has_feature(CPU_FTR_SMT)) |
237 | sysdev_create_file(s, &attr_purr); | 237 | sysdev_create_file(s, &attr_purr); |
238 | } | 238 | } |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index a6282b625b44..260b6ecd26a9 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -271,13 +271,13 @@ static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec, | |||
271 | * tb_to_xs and stamp_xsec values are consistent. If not, then it | 271 | * tb_to_xs and stamp_xsec values are consistent. If not, then it |
272 | * loops back and reads them again until this criteria is met. | 272 | * loops back and reads them again until this criteria is met. |
273 | */ | 273 | */ |
274 | ++(systemcfg->tb_update_count); | 274 | ++(_systemcfg->tb_update_count); |
275 | smp_wmb(); | 275 | smp_wmb(); |
276 | systemcfg->tb_orig_stamp = new_tb_stamp; | 276 | _systemcfg->tb_orig_stamp = new_tb_stamp; |
277 | systemcfg->stamp_xsec = new_stamp_xsec; | 277 | _systemcfg->stamp_xsec = new_stamp_xsec; |
278 | systemcfg->tb_to_xs = new_tb_to_xs; | 278 | _systemcfg->tb_to_xs = new_tb_to_xs; |
279 | smp_wmb(); | 279 | smp_wmb(); |
280 | ++(systemcfg->tb_update_count); | 280 | ++(_systemcfg->tb_update_count); |
281 | #endif | 281 | #endif |
282 | } | 282 | } |
283 | 283 | ||
@@ -357,8 +357,9 @@ static void iSeries_tb_recal(void) | |||
357 | do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; | 357 | do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; |
358 | tb_to_xs = divres.result_low; | 358 | tb_to_xs = divres.result_low; |
359 | do_gtod.varp->tb_to_xs = tb_to_xs; | 359 | do_gtod.varp->tb_to_xs = tb_to_xs; |
360 | systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; | 360 | _systemcfg->tb_ticks_per_sec = |
361 | systemcfg->tb_to_xs = tb_to_xs; | 361 | tb_ticks_per_sec; |
362 | _systemcfg->tb_to_xs = tb_to_xs; | ||
362 | } | 363 | } |
363 | else { | 364 | else { |
364 | printk( "Titan recalibrate: FAILED (difference > 4 percent)\n" | 365 | printk( "Titan recalibrate: FAILED (difference > 4 percent)\n" |
@@ -483,6 +484,8 @@ void __init smp_space_timers(unsigned int max_cpus) | |||
483 | unsigned long offset = tb_ticks_per_jiffy / max_cpus; | 484 | unsigned long offset = tb_ticks_per_jiffy / max_cpus; |
484 | unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid); | 485 | unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid); |
485 | 486 | ||
487 | /* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */ | ||
488 | previous_tb -= tb_ticks_per_jiffy; | ||
486 | for_each_cpu(i) { | 489 | for_each_cpu(i) { |
487 | if (i != boot_cpuid) { | 490 | if (i != boot_cpuid) { |
488 | previous_tb += offset; | 491 | previous_tb += offset; |
@@ -559,8 +562,8 @@ int do_settimeofday(struct timespec *tv) | |||
559 | update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs); | 562 | update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs); |
560 | 563 | ||
561 | #ifdef CONFIG_PPC64 | 564 | #ifdef CONFIG_PPC64 |
562 | systemcfg->tz_minuteswest = sys_tz.tz_minuteswest; | 565 | _systemcfg->tz_minuteswest = sys_tz.tz_minuteswest; |
563 | systemcfg->tz_dsttime = sys_tz.tz_dsttime; | 566 | _systemcfg->tz_dsttime = sys_tz.tz_dsttime; |
564 | #endif | 567 | #endif |
565 | 568 | ||
566 | write_sequnlock_irqrestore(&xtime_lock, flags); | 569 | write_sequnlock_irqrestore(&xtime_lock, flags); |
@@ -711,11 +714,11 @@ void __init time_init(void) | |||
711 | do_gtod.varp->tb_to_xs = tb_to_xs; | 714 | do_gtod.varp->tb_to_xs = tb_to_xs; |
712 | do_gtod.tb_to_us = tb_to_us; | 715 | do_gtod.tb_to_us = tb_to_us; |
713 | #ifdef CONFIG_PPC64 | 716 | #ifdef CONFIG_PPC64 |
714 | systemcfg->tb_orig_stamp = tb_last_jiffy; | 717 | _systemcfg->tb_orig_stamp = tb_last_jiffy; |
715 | systemcfg->tb_update_count = 0; | 718 | _systemcfg->tb_update_count = 0; |
716 | systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; | 719 | _systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; |
717 | systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; | 720 | _systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; |
718 | systemcfg->tb_to_xs = tb_to_xs; | 721 | _systemcfg->tb_to_xs = tb_to_xs; |
719 | #endif | 722 | #endif |
720 | 723 | ||
721 | time_freq = 0; | 724 | time_freq = 0; |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 0578f8387603..2020bb7648fb 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -129,7 +129,7 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
129 | nl = 1; | 129 | nl = 1; |
130 | #endif | 130 | #endif |
131 | #ifdef CONFIG_PPC64 | 131 | #ifdef CONFIG_PPC64 |
132 | switch (systemcfg->platform) { | 132 | switch (_machine) { |
133 | case PLATFORM_PSERIES: | 133 | case PLATFORM_PSERIES: |
134 | printk("PSERIES "); | 134 | printk("PSERIES "); |
135 | nl = 1; | 135 | nl = 1; |
diff --git a/arch/powerpc/lib/bitops.c b/arch/powerpc/lib/bitops.c index b67ce3004ebf..f68ad71a0187 100644 --- a/arch/powerpc/lib/bitops.c +++ b/arch/powerpc/lib/bitops.c | |||
@@ -41,7 +41,7 @@ unsigned long find_next_bit(const unsigned long *addr, unsigned long size, | |||
41 | tmp = *p; | 41 | tmp = *p; |
42 | 42 | ||
43 | found_first: | 43 | found_first: |
44 | tmp &= (~0UL >> (64 - size)); | 44 | tmp &= (~0UL >> (BITS_PER_LONG - size)); |
45 | if (tmp == 0UL) /* Are any bits set? */ | 45 | if (tmp == 0UL) /* Are any bits set? */ |
46 | return result + size; /* Nope. */ | 46 | return result + size; /* Nope. */ |
47 | found_middle: | 47 | found_middle: |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 22e474876133..706e8a63ced9 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -84,10 +84,11 @@ | |||
84 | extern unsigned long dart_tablebase; | 84 | extern unsigned long dart_tablebase; |
85 | #endif /* CONFIG_U3_DART */ | 85 | #endif /* CONFIG_U3_DART */ |
86 | 86 | ||
87 | static unsigned long _SDR1; | ||
88 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; | ||
89 | |||
87 | hpte_t *htab_address; | 90 | hpte_t *htab_address; |
88 | unsigned long htab_hash_mask; | 91 | unsigned long htab_hash_mask; |
89 | unsigned long _SDR1; | ||
90 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; | ||
91 | int mmu_linear_psize = MMU_PAGE_4K; | 92 | int mmu_linear_psize = MMU_PAGE_4K; |
92 | int mmu_virtual_psize = MMU_PAGE_4K; | 93 | int mmu_virtual_psize = MMU_PAGE_4K; |
93 | #ifdef CONFIG_HUGETLB_PAGE | 94 | #ifdef CONFIG_HUGETLB_PAGE |
@@ -165,7 +166,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, | |||
165 | * normal insert callback here. | 166 | * normal insert callback here. |
166 | */ | 167 | */ |
167 | #ifdef CONFIG_PPC_ISERIES | 168 | #ifdef CONFIG_PPC_ISERIES |
168 | if (systemcfg->platform == PLATFORM_ISERIES_LPAR) | 169 | if (_machine == PLATFORM_ISERIES_LPAR) |
169 | ret = iSeries_hpte_insert(hpteg, va, | 170 | ret = iSeries_hpte_insert(hpteg, va, |
170 | virt_to_abs(paddr), | 171 | virt_to_abs(paddr), |
171 | tmp_mode, | 172 | tmp_mode, |
@@ -174,7 +175,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, | |||
174 | else | 175 | else |
175 | #endif | 176 | #endif |
176 | #ifdef CONFIG_PPC_PSERIES | 177 | #ifdef CONFIG_PPC_PSERIES |
177 | if (systemcfg->platform & PLATFORM_LPAR) | 178 | if (_machine & PLATFORM_LPAR) |
178 | ret = pSeries_lpar_hpte_insert(hpteg, va, | 179 | ret = pSeries_lpar_hpte_insert(hpteg, va, |
179 | virt_to_abs(paddr), | 180 | virt_to_abs(paddr), |
180 | tmp_mode, | 181 | tmp_mode, |
@@ -293,7 +294,7 @@ static void __init htab_init_page_sizes(void) | |||
293 | * Not in the device-tree, let's fallback on known size | 294 | * Not in the device-tree, let's fallback on known size |
294 | * list for 16M capable GP & GR | 295 | * list for 16M capable GP & GR |
295 | */ | 296 | */ |
296 | if ((systemcfg->platform != PLATFORM_ISERIES_LPAR) && | 297 | if ((_machine != PLATFORM_ISERIES_LPAR) && |
297 | cpu_has_feature(CPU_FTR_16M_PAGE)) | 298 | cpu_has_feature(CPU_FTR_16M_PAGE)) |
298 | memcpy(mmu_psize_defs, mmu_psize_defaults_gp, | 299 | memcpy(mmu_psize_defs, mmu_psize_defaults_gp, |
299 | sizeof(mmu_psize_defaults_gp)); | 300 | sizeof(mmu_psize_defaults_gp)); |
@@ -364,7 +365,7 @@ static int __init htab_dt_scan_pftsize(unsigned long node, | |||
364 | 365 | ||
365 | static unsigned long __init htab_get_table_size(void) | 366 | static unsigned long __init htab_get_table_size(void) |
366 | { | 367 | { |
367 | unsigned long rnd_mem_size, pteg_count; | 368 | unsigned long mem_size, rnd_mem_size, pteg_count; |
368 | 369 | ||
369 | /* If hash size isn't already provided by the platform, we try to | 370 | /* If hash size isn't already provided by the platform, we try to |
370 | * retreive it from the device-tree. If it's not there neither, we | 371 | * retreive it from the device-tree. If it's not there neither, we |
@@ -376,8 +377,9 @@ static unsigned long __init htab_get_table_size(void) | |||
376 | return 1UL << ppc64_pft_size; | 377 | return 1UL << ppc64_pft_size; |
377 | 378 | ||
378 | /* round mem_size up to next power of 2 */ | 379 | /* round mem_size up to next power of 2 */ |
379 | rnd_mem_size = 1UL << __ilog2(systemcfg->physicalMemorySize); | 380 | mem_size = lmb_phys_mem_size(); |
380 | if (rnd_mem_size < systemcfg->physicalMemorySize) | 381 | rnd_mem_size = 1UL << __ilog2(mem_size); |
382 | if (rnd_mem_size < mem_size) | ||
381 | rnd_mem_size <<= 1; | 383 | rnd_mem_size <<= 1; |
382 | 384 | ||
383 | /* # pages / 2 */ | 385 | /* # pages / 2 */ |
@@ -386,6 +388,15 @@ static unsigned long __init htab_get_table_size(void) | |||
386 | return pteg_count << 7; | 388 | return pteg_count << 7; |
387 | } | 389 | } |
388 | 390 | ||
391 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
392 | void create_section_mapping(unsigned long start, unsigned long end) | ||
393 | { | ||
394 | BUG_ON(htab_bolt_mapping(start, end, start, | ||
395 | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX, | ||
396 | mmu_linear_psize)); | ||
397 | } | ||
398 | #endif /* CONFIG_MEMORY_HOTPLUG */ | ||
399 | |||
389 | void __init htab_initialize(void) | 400 | void __init htab_initialize(void) |
390 | { | 401 | { |
391 | unsigned long table, htab_size_bytes; | 402 | unsigned long table, htab_size_bytes; |
@@ -410,7 +421,7 @@ void __init htab_initialize(void) | |||
410 | 421 | ||
411 | htab_hash_mask = pteg_count - 1; | 422 | htab_hash_mask = pteg_count - 1; |
412 | 423 | ||
413 | if (systemcfg->platform & PLATFORM_LPAR) { | 424 | if (platform_is_lpar()) { |
414 | /* Using a hypervisor which owns the htab */ | 425 | /* Using a hypervisor which owns the htab */ |
415 | htab_address = NULL; | 426 | htab_address = NULL; |
416 | _SDR1 = 0; | 427 | _SDR1 = 0; |
@@ -431,6 +442,9 @@ void __init htab_initialize(void) | |||
431 | 442 | ||
432 | /* Initialize the HPT with no entries */ | 443 | /* Initialize the HPT with no entries */ |
433 | memset((void *)table, 0, htab_size_bytes); | 444 | memset((void *)table, 0, htab_size_bytes); |
445 | |||
446 | /* Set SDR1 */ | ||
447 | mtspr(SPRN_SDR1, _SDR1); | ||
434 | } | 448 | } |
435 | 449 | ||
436 | mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX; | 450 | mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX; |
@@ -500,6 +514,12 @@ void __init htab_initialize(void) | |||
500 | #undef KB | 514 | #undef KB |
501 | #undef MB | 515 | #undef MB |
502 | 516 | ||
517 | void __init htab_initialize_secondary(void) | ||
518 | { | ||
519 | if (!platform_is_lpar()) | ||
520 | mtspr(SPRN_SDR1, _SDR1); | ||
521 | } | ||
522 | |||
503 | /* | 523 | /* |
504 | * Called by asm hashtable.S for doing lazy icache flush | 524 | * Called by asm hashtable.S for doing lazy icache flush |
505 | */ | 525 | */ |
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 4612a79dfb6e..7d4b8b5f0606 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c | |||
@@ -84,9 +84,6 @@ void MMU_init(void); | |||
84 | /* XXX should be in current.h -- paulus */ | 84 | /* XXX should be in current.h -- paulus */ |
85 | extern struct task_struct *current_set[NR_CPUS]; | 85 | extern struct task_struct *current_set[NR_CPUS]; |
86 | 86 | ||
87 | char *klimit = _end; | ||
88 | struct device_node *memory_node; | ||
89 | |||
90 | extern int init_bootmem_done; | 87 | extern int init_bootmem_done; |
91 | 88 | ||
92 | /* | 89 | /* |
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index ce974c83d88a..1134f70f231d 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
@@ -20,6 +20,8 @@ | |||
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #undef DEBUG | ||
24 | |||
23 | #include <linux/config.h> | 25 | #include <linux/config.h> |
24 | #include <linux/signal.h> | 26 | #include <linux/signal.h> |
25 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
@@ -64,6 +66,12 @@ | |||
64 | #include <asm/vdso.h> | 66 | #include <asm/vdso.h> |
65 | #include <asm/imalloc.h> | 67 | #include <asm/imalloc.h> |
66 | 68 | ||
69 | #ifdef DEBUG | ||
70 | #define DBG(fmt...) printk(fmt) | ||
71 | #else | ||
72 | #define DBG(fmt...) | ||
73 | #endif | ||
74 | |||
67 | #if PGTABLE_RANGE > USER_VSID_RANGE | 75 | #if PGTABLE_RANGE > USER_VSID_RANGE |
68 | #warning Limited user VSID range means pagetable space is wasted | 76 | #warning Limited user VSID range means pagetable space is wasted |
69 | #endif | 77 | #endif |
@@ -72,8 +80,6 @@ | |||
72 | #warning TASK_SIZE is smaller than it needs to be. | 80 | #warning TASK_SIZE is smaller than it needs to be. |
73 | #endif | 81 | #endif |
74 | 82 | ||
75 | unsigned long klimit = (unsigned long)_end; | ||
76 | |||
77 | /* max amount of RAM to use */ | 83 | /* max amount of RAM to use */ |
78 | unsigned long __max_memory; | 84 | unsigned long __max_memory; |
79 | 85 | ||
@@ -188,14 +194,14 @@ static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags) | |||
188 | } | 194 | } |
189 | 195 | ||
190 | #ifdef CONFIG_PPC_64K_PAGES | 196 | #ifdef CONFIG_PPC_64K_PAGES |
191 | static const int pgtable_cache_size[2] = { | 197 | static const unsigned int pgtable_cache_size[3] = { |
192 | PTE_TABLE_SIZE, PGD_TABLE_SIZE | 198 | PTE_TABLE_SIZE, PMD_TABLE_SIZE, PGD_TABLE_SIZE |
193 | }; | 199 | }; |
194 | static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { | 200 | static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { |
195 | "pte_pmd_cache", "pgd_cache", | 201 | "pte_pmd_cache", "pmd_cache", "pgd_cache", |
196 | }; | 202 | }; |
197 | #else | 203 | #else |
198 | static const int pgtable_cache_size[2] = { | 204 | static const unsigned int pgtable_cache_size[2] = { |
199 | PTE_TABLE_SIZE, PMD_TABLE_SIZE | 205 | PTE_TABLE_SIZE, PMD_TABLE_SIZE |
200 | }; | 206 | }; |
201 | static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { | 207 | static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { |
@@ -213,6 +219,8 @@ void pgtable_cache_init(void) | |||
213 | int size = pgtable_cache_size[i]; | 219 | int size = pgtable_cache_size[i]; |
214 | const char *name = pgtable_cache_name[i]; | 220 | const char *name = pgtable_cache_name[i]; |
215 | 221 | ||
222 | DBG("Allocating page table cache %s (#%d) " | ||
223 | "for size: %08x...\n", name, i, size); | ||
216 | pgtable_cache[i] = kmem_cache_create(name, | 224 | pgtable_cache[i] = kmem_cache_create(name, |
217 | size, size, | 225 | size, size, |
218 | SLAB_HWCACHE_ALIGN | | 226 | SLAB_HWCACHE_ALIGN | |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 6f55efd9be95..1dd3cc69a490 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -110,6 +110,7 @@ EXPORT_SYMBOL(phys_mem_access_prot); | |||
110 | void online_page(struct page *page) | 110 | void online_page(struct page *page) |
111 | { | 111 | { |
112 | ClearPageReserved(page); | 112 | ClearPageReserved(page); |
113 | set_page_count(page, 0); | ||
113 | free_cold_page(page); | 114 | free_cold_page(page); |
114 | totalram_pages++; | 115 | totalram_pages++; |
115 | num_physpages++; | 116 | num_physpages++; |
@@ -127,6 +128,9 @@ int __devinit add_memory(u64 start, u64 size) | |||
127 | unsigned long start_pfn = start >> PAGE_SHIFT; | 128 | unsigned long start_pfn = start >> PAGE_SHIFT; |
128 | unsigned long nr_pages = size >> PAGE_SHIFT; | 129 | unsigned long nr_pages = size >> PAGE_SHIFT; |
129 | 130 | ||
131 | start += KERNELBASE; | ||
132 | create_section_mapping(start, start + size); | ||
133 | |||
130 | /* this should work for most non-highmem platforms */ | 134 | /* this should work for most non-highmem platforms */ |
131 | zone = pgdata->node_zones; | 135 | zone = pgdata->node_zones; |
132 | 136 | ||
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 900842451bd3..c7f7bb6f30b3 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
@@ -122,8 +122,11 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) | |||
122 | * | 122 | * |
123 | */ | 123 | */ |
124 | if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags, | 124 | if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags, |
125 | mmu_virtual_psize)) | 125 | mmu_virtual_psize)) { |
126 | panic("Can't map bolted IO mapping"); | 126 | printk(KERN_ERR "Failed to do bolted mapping IO " |
127 | "memory at %016lx !\n", pa); | ||
128 | return -ENOMEM; | ||
129 | } | ||
127 | } | 130 | } |
128 | return 0; | 131 | return 0; |
129 | } | 132 | } |
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c index fa325dbf98fc..cfbb4e1f966b 100644 --- a/arch/powerpc/mm/stab.c +++ b/arch/powerpc/mm/stab.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <asm/cputable.h> | 20 | #include <asm/cputable.h> |
21 | #include <asm/lmb.h> | 21 | #include <asm/lmb.h> |
22 | #include <asm/abs_addr.h> | 22 | #include <asm/abs_addr.h> |
23 | #include <asm/firmware.h> | ||
23 | 24 | ||
24 | struct stab_entry { | 25 | struct stab_entry { |
25 | unsigned long esid_data; | 26 | unsigned long esid_data; |
@@ -256,7 +257,7 @@ void stabs_alloc(void) | |||
256 | 257 | ||
257 | paca[cpu].stab_addr = newstab; | 258 | paca[cpu].stab_addr = newstab; |
258 | paca[cpu].stab_real = virt_to_abs(newstab); | 259 | paca[cpu].stab_real = virt_to_abs(newstab); |
259 | printk(KERN_DEBUG "Segment table for CPU %d at 0x%lx " | 260 | printk(KERN_INFO "Segment table for CPU %d at 0x%lx " |
260 | "virtual, 0x%lx absolute\n", | 261 | "virtual, 0x%lx absolute\n", |
261 | cpu, paca[cpu].stab_addr, paca[cpu].stab_real); | 262 | cpu, paca[cpu].stab_addr, paca[cpu].stab_real); |
262 | } | 263 | } |
@@ -270,10 +271,28 @@ void stabs_alloc(void) | |||
270 | void stab_initialize(unsigned long stab) | 271 | void stab_initialize(unsigned long stab) |
271 | { | 272 | { |
272 | unsigned long vsid = get_kernel_vsid(KERNELBASE); | 273 | unsigned long vsid = get_kernel_vsid(KERNELBASE); |
274 | unsigned long stabreal; | ||
273 | 275 | ||
274 | asm volatile("isync; slbia; isync":::"memory"); | 276 | asm volatile("isync; slbia; isync":::"memory"); |
275 | make_ste(stab, GET_ESID(KERNELBASE), vsid); | 277 | make_ste(stab, GET_ESID(KERNELBASE), vsid); |
276 | 278 | ||
277 | /* Order update */ | 279 | /* Order update */ |
278 | asm volatile("sync":::"memory"); | 280 | asm volatile("sync":::"memory"); |
281 | |||
282 | /* Set ASR */ | ||
283 | stabreal = get_paca()->stab_real | 0x1ul; | ||
284 | |||
285 | #ifdef CONFIG_PPC_ISERIES | ||
286 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | ||
287 | HvCall1(HvCallBaseSetASR, stabreal); | ||
288 | return; | ||
289 | } | ||
290 | #endif /* CONFIG_PPC_ISERIES */ | ||
291 | #ifdef CONFIG_PPC_PSERIES | ||
292 | if (platform_is_lpar()) { | ||
293 | plpar_hcall_norets(H_SET_ASR, stabreal); | ||
294 | return; | ||
295 | } | ||
296 | #endif | ||
297 | mtspr(SPRN_ASR, stabreal); | ||
279 | } | 298 | } |
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index c4ee5478427b..e3a024e324b6 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c | |||
@@ -233,8 +233,7 @@ static unsigned long get_pc(struct pt_regs *regs) | |||
233 | mmcra = mfspr(SPRN_MMCRA); | 233 | mmcra = mfspr(SPRN_MMCRA); |
234 | 234 | ||
235 | /* Were we in the hypervisor? */ | 235 | /* Were we in the hypervisor? */ |
236 | if ((systemcfg->platform == PLATFORM_PSERIES_LPAR) && | 236 | if (platform_is_lpar() && (mmcra & MMCRA_SIHV)) |
237 | (mmcra & MMCRA_SIHV)) | ||
238 | /* function descriptor madness */ | 237 | /* function descriptor madness */ |
239 | return *((unsigned long *)hypervisor_bucket); | 238 | return *((unsigned long *)hypervisor_bucket); |
240 | 239 | ||
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index ecd32d5d85f4..4099ddab9205 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -361,7 +361,9 @@ static void __init chrp_find_openpic(void) | |||
361 | printk(KERN_INFO "OpenPIC at %lx\n", opaddr); | 361 | printk(KERN_INFO "OpenPIC at %lx\n", opaddr); |
362 | 362 | ||
363 | irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */ | 363 | irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */ |
364 | prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS - 4); | 364 | prom_get_irq_senses(init_senses, NUM_ISA_INTERRUPTS, NR_IRQS - 4); |
365 | /* i8259 cascade is always positive level */ | ||
366 | init_senses[0] = IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE; | ||
365 | 367 | ||
366 | iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len); | 368 | iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len); |
367 | if (iranges == NULL) | 369 | if (iranges == NULL) |
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index a06603d84a45..01090e9ce0cf 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c | |||
@@ -103,6 +103,9 @@ static void intReceived(struct XmPciLpEvent *eventParm, | |||
103 | struct pt_regs *regsParm) | 103 | struct pt_regs *regsParm) |
104 | { | 104 | { |
105 | int irq; | 105 | int irq; |
106 | #ifdef CONFIG_IRQSTACKS | ||
107 | struct thread_info *curtp, *irqtp; | ||
108 | #endif | ||
106 | 109 | ||
107 | ++Pci_Interrupt_Count; | 110 | ++Pci_Interrupt_Count; |
108 | 111 | ||
@@ -110,7 +113,20 @@ static void intReceived(struct XmPciLpEvent *eventParm, | |||
110 | case XmPciLpEvent_SlotInterrupt: | 113 | case XmPciLpEvent_SlotInterrupt: |
111 | irq = eventParm->hvLpEvent.xCorrelationToken; | 114 | irq = eventParm->hvLpEvent.xCorrelationToken; |
112 | /* Dispatch the interrupt handlers for this irq */ | 115 | /* Dispatch the interrupt handlers for this irq */ |
113 | ppc_irq_dispatch_handler(regsParm, irq); | 116 | #ifdef CONFIG_IRQSTACKS |
117 | /* Switch to the irq stack to handle this */ | ||
118 | curtp = current_thread_info(); | ||
119 | irqtp = hardirq_ctx[smp_processor_id()]; | ||
120 | if (curtp != irqtp) { | ||
121 | irqtp->task = curtp->task; | ||
122 | irqtp->flags = 0; | ||
123 | call___do_IRQ(irq, regsParm, irqtp); | ||
124 | irqtp->task = NULL; | ||
125 | if (irqtp->flags) | ||
126 | set_bits(irqtp->flags, &curtp->flags); | ||
127 | } else | ||
128 | #endif | ||
129 | __do_IRQ(irq, regsParm); | ||
114 | HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber, | 130 | HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber, |
115 | eventParm->eventData.slotInterrupt.subBusNumber, | 131 | eventParm->eventData.slotInterrupt.subBusNumber, |
116 | eventParm->eventData.slotInterrupt.deviceId); | 132 | eventParm->eventData.slotInterrupt.deviceId); |
@@ -310,10 +326,8 @@ static void iSeries_disable_IRQ(unsigned int irq) | |||
310 | } | 326 | } |
311 | 327 | ||
312 | /* | 328 | /* |
313 | * Need to define this so ppc_irq_dispatch_handler will NOT call | 329 | * This does nothing because there is not enough information |
314 | * enable_IRQ at the end of interrupt handling. However, this does | 330 | * provided to do the EOI HvCall. This is done by XmPciLpEvent.c |
315 | * nothing because there is not enough information provided to do | ||
316 | * the EOI HvCall. This is done by XmPciLpEvent.c | ||
317 | */ | 331 | */ |
318 | static void iSeries_end_IRQ(unsigned int irq) | 332 | static void iSeries_end_IRQ(unsigned int irq) |
319 | { | 333 | { |
diff --git a/arch/powerpc/platforms/iseries/misc.S b/arch/powerpc/platforms/iseries/misc.S index 09f14522e176..dfe7aa1ba098 100644 --- a/arch/powerpc/platforms/iseries/misc.S +++ b/arch/powerpc/platforms/iseries/misc.S | |||
@@ -15,6 +15,7 @@ | |||
15 | 15 | ||
16 | #include <asm/processor.h> | 16 | #include <asm/processor.h> |
17 | #include <asm/asm-offsets.h> | 17 | #include <asm/asm-offsets.h> |
18 | #include <asm/ppc_asm.h> | ||
18 | 19 | ||
19 | .text | 20 | .text |
20 | 21 | ||
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 7f8f0cda6a74..6a29f301436b 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c | |||
@@ -39,7 +39,8 @@ | |||
39 | #include <asm/sections.h> | 39 | #include <asm/sections.h> |
40 | #include <asm/iommu.h> | 40 | #include <asm/iommu.h> |
41 | #include <asm/firmware.h> | 41 | #include <asm/firmware.h> |
42 | 42 | #include <asm/systemcfg.h> | |
43 | #include <asm/system.h> | ||
43 | #include <asm/time.h> | 44 | #include <asm/time.h> |
44 | #include <asm/paca.h> | 45 | #include <asm/paca.h> |
45 | #include <asm/cache.h> | 46 | #include <asm/cache.h> |
@@ -71,7 +72,7 @@ extern void hvlog(char *fmt, ...); | |||
71 | #endif | 72 | #endif |
72 | 73 | ||
73 | /* Function Prototypes */ | 74 | /* Function Prototypes */ |
74 | static void build_iSeries_Memory_Map(void); | 75 | static unsigned long build_iSeries_Memory_Map(void); |
75 | static void iseries_shared_idle(void); | 76 | static void iseries_shared_idle(void); |
76 | static void iseries_dedicated_idle(void); | 77 | static void iseries_dedicated_idle(void); |
77 | #ifdef CONFIG_PCI | 78 | #ifdef CONFIG_PCI |
@@ -84,7 +85,6 @@ static void iSeries_pci_final_fixup(void) { } | |||
84 | int piranha_simulator; | 85 | int piranha_simulator; |
85 | 86 | ||
86 | extern int rd_size; /* Defined in drivers/block/rd.c */ | 87 | extern int rd_size; /* Defined in drivers/block/rd.c */ |
87 | extern unsigned long klimit; | ||
88 | extern unsigned long embedded_sysmap_start; | 88 | extern unsigned long embedded_sysmap_start; |
89 | extern unsigned long embedded_sysmap_end; | 89 | extern unsigned long embedded_sysmap_end; |
90 | 90 | ||
@@ -403,9 +403,11 @@ void mschunks_alloc(unsigned long num_chunks) | |||
403 | * a table used to translate Linux's physical addresses to these | 403 | * a table used to translate Linux's physical addresses to these |
404 | * absolute addresses. Absolute addresses are needed when | 404 | * absolute addresses. Absolute addresses are needed when |
405 | * communicating with the hypervisor (e.g. to build HPT entries) | 405 | * communicating with the hypervisor (e.g. to build HPT entries) |
406 | * | ||
407 | * Returns the physical memory size | ||
406 | */ | 408 | */ |
407 | 409 | ||
408 | static void __init build_iSeries_Memory_Map(void) | 410 | static unsigned long __init build_iSeries_Memory_Map(void) |
409 | { | 411 | { |
410 | u32 loadAreaFirstChunk, loadAreaLastChunk, loadAreaSize; | 412 | u32 loadAreaFirstChunk, loadAreaLastChunk, loadAreaSize; |
411 | u32 nextPhysChunk; | 413 | u32 nextPhysChunk; |
@@ -538,7 +540,7 @@ static void __init build_iSeries_Memory_Map(void) | |||
538 | * which should be equal to | 540 | * which should be equal to |
539 | * nextPhysChunk | 541 | * nextPhysChunk |
540 | */ | 542 | */ |
541 | systemcfg->physicalMemorySize = chunk_to_addr(nextPhysChunk); | 543 | return chunk_to_addr(nextPhysChunk); |
542 | } | 544 | } |
543 | 545 | ||
544 | /* | 546 | /* |
@@ -564,8 +566,8 @@ static void __init iSeries_setup_arch(void) | |||
564 | printk("Max physical processors = %d\n", | 566 | printk("Max physical processors = %d\n", |
565 | itVpdAreas.xSlicMaxPhysicalProcs); | 567 | itVpdAreas.xSlicMaxPhysicalProcs); |
566 | 568 | ||
567 | systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR; | 569 | _systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR; |
568 | printk("Processor version = %x\n", systemcfg->processor); | 570 | printk("Processor version = %x\n", _systemcfg->processor); |
569 | } | 571 | } |
570 | 572 | ||
571 | static void iSeries_show_cpuinfo(struct seq_file *m) | 573 | static void iSeries_show_cpuinfo(struct seq_file *m) |
@@ -702,7 +704,6 @@ static void iseries_shared_idle(void) | |||
702 | 704 | ||
703 | static void iseries_dedicated_idle(void) | 705 | static void iseries_dedicated_idle(void) |
704 | { | 706 | { |
705 | long oldval; | ||
706 | set_thread_flag(TIF_POLLING_NRFLAG); | 707 | set_thread_flag(TIF_POLLING_NRFLAG); |
707 | 708 | ||
708 | while (1) { | 709 | while (1) { |
@@ -929,7 +930,7 @@ void dt_cpus(struct iseries_flat_dt *dt) | |||
929 | dt_end_node(dt); | 930 | dt_end_node(dt); |
930 | } | 931 | } |
931 | 932 | ||
932 | void build_flat_dt(struct iseries_flat_dt *dt) | 933 | void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) |
933 | { | 934 | { |
934 | u64 tmp[2]; | 935 | u64 tmp[2]; |
935 | 936 | ||
@@ -945,7 +946,7 @@ void build_flat_dt(struct iseries_flat_dt *dt) | |||
945 | dt_prop_str(dt, "name", "memory"); | 946 | dt_prop_str(dt, "name", "memory"); |
946 | dt_prop_str(dt, "device_type", "memory"); | 947 | dt_prop_str(dt, "device_type", "memory"); |
947 | tmp[0] = 0; | 948 | tmp[0] = 0; |
948 | tmp[1] = systemcfg->physicalMemorySize; | 949 | tmp[1] = phys_mem_size; |
949 | dt_prop_u64_list(dt, "reg", tmp, 2); | 950 | dt_prop_u64_list(dt, "reg", tmp, 2); |
950 | dt_end_node(dt); | 951 | dt_end_node(dt); |
951 | 952 | ||
@@ -965,13 +966,15 @@ void build_flat_dt(struct iseries_flat_dt *dt) | |||
965 | 966 | ||
966 | void * __init iSeries_early_setup(void) | 967 | void * __init iSeries_early_setup(void) |
967 | { | 968 | { |
969 | unsigned long phys_mem_size; | ||
970 | |||
968 | iSeries_fixup_klimit(); | 971 | iSeries_fixup_klimit(); |
969 | 972 | ||
970 | /* | 973 | /* |
971 | * Initialize the table which translate Linux physical addresses to | 974 | * Initialize the table which translate Linux physical addresses to |
972 | * AS/400 absolute addresses | 975 | * AS/400 absolute addresses |
973 | */ | 976 | */ |
974 | build_iSeries_Memory_Map(); | 977 | phys_mem_size = build_iSeries_Memory_Map(); |
975 | 978 | ||
976 | iSeries_get_cmdline(); | 979 | iSeries_get_cmdline(); |
977 | 980 | ||
@@ -981,7 +984,7 @@ void * __init iSeries_early_setup(void) | |||
981 | /* Parse early parameters, in particular mem=x */ | 984 | /* Parse early parameters, in particular mem=x */ |
982 | parse_early_param(); | 985 | parse_early_param(); |
983 | 986 | ||
984 | build_flat_dt(&iseries_dt); | 987 | build_flat_dt(&iseries_dt, phys_mem_size); |
985 | 988 | ||
986 | return (void *) __pa(&iseries_dt); | 989 | return (void *) __pa(&iseries_dt); |
987 | } | 990 | } |
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index 340c21caeae2..895aeb3f75d0 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c | |||
@@ -380,9 +380,6 @@ void __init maple_pcibios_fixup(void) | |||
380 | for_each_pci_dev(dev) | 380 | for_each_pci_dev(dev) |
381 | pci_read_irq_line(dev); | 381 | pci_read_irq_line(dev); |
382 | 382 | ||
383 | /* Do the mapping of the IO space */ | ||
384 | phbs_remap_io(); | ||
385 | |||
386 | DBG(" <- maple_pcibios_fixup\n"); | 383 | DBG(" <- maple_pcibios_fixup\n"); |
387 | } | 384 | } |
388 | 385 | ||
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 8f818d092e2b..dfd41b9781a9 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c | |||
@@ -918,9 +918,6 @@ void __init pmac_pci_init(void) | |||
918 | PCI_DN(np)->busno = 0xf0; | 918 | PCI_DN(np)->busno = 0xf0; |
919 | } | 919 | } |
920 | 920 | ||
921 | /* map in PCI I/O space */ | ||
922 | phbs_remap_io(); | ||
923 | |||
924 | /* pmac_check_ht_link(); */ | 921 | /* pmac_check_ht_link(); */ |
925 | 922 | ||
926 | /* Tell pci.c to not use the common resource allocation mechanism */ | 923 | /* Tell pci.c to not use the common resource allocation mechanism */ |
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index 83a49e80ac29..90040c49494d 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c | |||
@@ -74,6 +74,9 @@ static DEFINE_SPINLOCK(pmac_pic_lock); | |||
74 | #define GATWICK_IRQ_POOL_SIZE 10 | 74 | #define GATWICK_IRQ_POOL_SIZE 10 |
75 | static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; | 75 | static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; |
76 | 76 | ||
77 | #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) | ||
78 | static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; | ||
79 | |||
77 | /* | 80 | /* |
78 | * Mark an irq as "lost". This is only used on the pmac | 81 | * Mark an irq as "lost". This is only used on the pmac |
79 | * since it can lose interrupts (see pmac_set_irq_mask). | 82 | * since it can lose interrupts (see pmac_set_irq_mask). |
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index e1f9443cc872..957b09103422 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c | |||
@@ -305,9 +305,19 @@ static int __init smp_psurge_probe(void) | |||
305 | psurge_start = ioremap(PSURGE_START, 4); | 305 | psurge_start = ioremap(PSURGE_START, 4); |
306 | psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); | 306 | psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); |
307 | 307 | ||
308 | /* this is not actually strictly necessary -- paulus. */ | 308 | /* |
309 | for (i = 1; i < ncpus; ++i) | 309 | * This is necessary because OF doesn't know about the |
310 | smp_hw_index[i] = i; | 310 | * secondary cpu(s), and thus there aren't nodes in the |
311 | * device tree for them, and smp_setup_cpu_maps hasn't | ||
312 | * set their bits in cpu_possible_map and cpu_present_map. | ||
313 | */ | ||
314 | if (ncpus > NR_CPUS) | ||
315 | ncpus = NR_CPUS; | ||
316 | for (i = 1; i < ncpus ; ++i) { | ||
317 | cpu_set(i, cpu_present_map); | ||
318 | cpu_set(i, cpu_possible_map); | ||
319 | set_hard_smp_processor_id(i, i); | ||
320 | } | ||
311 | 321 | ||
312 | if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352); | 322 | if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352); |
313 | 323 | ||
@@ -348,6 +358,7 @@ static void __init psurge_dual_sync_tb(int cpu_nr) | |||
348 | int t; | 358 | int t; |
349 | 359 | ||
350 | set_dec(tb_ticks_per_jiffy); | 360 | set_dec(tb_ticks_per_jiffy); |
361 | /* XXX fixme */ | ||
351 | set_tb(0, 0); | 362 | set_tb(0, 0); |
352 | last_jiffy_stamp(cpu_nr) = 0; | 363 | last_jiffy_stamp(cpu_nr) = 0; |
353 | 364 | ||
@@ -363,8 +374,6 @@ static void __init psurge_dual_sync_tb(int cpu_nr) | |||
363 | 374 | ||
364 | /* now interrupt the secondary, starting both TBs */ | 375 | /* now interrupt the secondary, starting both TBs */ |
365 | psurge_set_ipi(1); | 376 | psurge_set_ipi(1); |
366 | |||
367 | smp_tb_synchronized = 1; | ||
368 | } | 377 | } |
369 | 378 | ||
370 | static struct irqaction psurge_irqaction = { | 379 | static struct irqaction psurge_irqaction = { |
@@ -625,9 +634,8 @@ void smp_core99_give_timebase(void) | |||
625 | for (t = 100000; t > 0 && sec_tb_reset; --t) | 634 | for (t = 100000; t > 0 && sec_tb_reset; --t) |
626 | udelay(10); | 635 | udelay(10); |
627 | if (sec_tb_reset) | 636 | if (sec_tb_reset) |
637 | /* XXX BUG_ON here? */ | ||
628 | printk(KERN_WARNING "Timeout waiting sync(2) on second CPU\n"); | 638 | printk(KERN_WARNING "Timeout waiting sync(2) on second CPU\n"); |
629 | else | ||
630 | smp_tb_synchronized = 1; | ||
631 | 639 | ||
632 | /* Now, restart the timebase by leaving the GPIO to an open collector */ | 640 | /* Now, restart the timebase by leaving the GPIO to an open collector */ |
633 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0); | 641 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0); |
@@ -810,19 +818,9 @@ static void __devinit smp_core99_setup_cpu(int cpu_nr) | |||
810 | } | 818 | } |
811 | 819 | ||
812 | 820 | ||
813 | /* Core99 Macs (dual G4s and G5s) */ | ||
814 | struct smp_ops_t core99_smp_ops = { | ||
815 | .message_pass = smp_mpic_message_pass, | ||
816 | .probe = smp_core99_probe, | ||
817 | .kick_cpu = smp_core99_kick_cpu, | ||
818 | .setup_cpu = smp_core99_setup_cpu, | ||
819 | .give_timebase = smp_core99_give_timebase, | ||
820 | .take_timebase = smp_core99_take_timebase, | ||
821 | }; | ||
822 | |||
823 | #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32) | 821 | #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32) |
824 | 822 | ||
825 | int __cpu_disable(void) | 823 | int smp_core99_cpu_disable(void) |
826 | { | 824 | { |
827 | cpu_clear(smp_processor_id(), cpu_online_map); | 825 | cpu_clear(smp_processor_id(), cpu_online_map); |
828 | 826 | ||
@@ -846,7 +844,7 @@ void cpu_die(void) | |||
846 | low_cpu_die(); | 844 | low_cpu_die(); |
847 | } | 845 | } |
848 | 846 | ||
849 | void __cpu_die(unsigned int cpu) | 847 | void smp_core99_cpu_die(unsigned int cpu) |
850 | { | 848 | { |
851 | int timeout; | 849 | int timeout; |
852 | 850 | ||
@@ -858,8 +856,21 @@ void __cpu_die(unsigned int cpu) | |||
858 | } | 856 | } |
859 | msleep(1); | 857 | msleep(1); |
860 | } | 858 | } |
861 | cpu_callin_map[cpu] = 0; | ||
862 | cpu_dead[cpu] = 0; | 859 | cpu_dead[cpu] = 0; |
863 | } | 860 | } |
864 | 861 | ||
865 | #endif | 862 | #endif |
863 | |||
864 | /* Core99 Macs (dual G4s and G5s) */ | ||
865 | struct smp_ops_t core99_smp_ops = { | ||
866 | .message_pass = smp_mpic_message_pass, | ||
867 | .probe = smp_core99_probe, | ||
868 | .kick_cpu = smp_core99_kick_cpu, | ||
869 | .setup_cpu = smp_core99_setup_cpu, | ||
870 | .give_timebase = smp_core99_give_timebase, | ||
871 | .take_timebase = smp_core99_take_timebase, | ||
872 | #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32) | ||
873 | .cpu_disable = smp_core99_cpu_disable, | ||
874 | .cpu_die = smp_core99_cpu_die, | ||
875 | #endif | ||
876 | }; | ||
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index b9938fece781..e7ca5b1f591e 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -3,3 +3,5 @@ obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ | |||
3 | obj-$(CONFIG_SMP) += smp.o | 3 | obj-$(CONFIG_SMP) += smp.o |
4 | obj-$(CONFIG_IBMVIO) += vio.o | 4 | obj-$(CONFIG_IBMVIO) += vio.o |
5 | obj-$(CONFIG_XICS) += xics.o | 5 | obj-$(CONFIG_XICS) += xics.o |
6 | obj-$(CONFIG_SCANLOG) += scanlog.o | ||
7 | obj-$(CONFIG_EEH) += eeh.o eeh_event.o | ||
diff --git a/arch/ppc64/kernel/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 035d1b14a207..79de2310e70b 100644 --- a/arch/ppc64/kernel/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
@@ -1,39 +1,37 @@ | |||
1 | /* | 1 | /* |
2 | * eeh.c | 2 | * eeh.c |
3 | * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation | 3 | * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or | 7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. | 8 | * (at your option) any later version. |
9 | * | 9 | * |
10 | * This program is distributed in the hope that it will be useful, | 10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
14 | * | 14 | * |
15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program; if not, write to the Free Software | 16 | * along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/bootmem.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/list.h> | 22 | #include <linux/list.h> |
23 | #include <linux/mm.h> | ||
24 | #include <linux/notifier.h> | ||
25 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
26 | #include <linux/proc_fs.h> | 24 | #include <linux/proc_fs.h> |
27 | #include <linux/rbtree.h> | 25 | #include <linux/rbtree.h> |
28 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
29 | #include <linux/spinlock.h> | 27 | #include <linux/spinlock.h> |
28 | #include <asm/atomic.h> | ||
30 | #include <asm/eeh.h> | 29 | #include <asm/eeh.h> |
30 | #include <asm/eeh_event.h> | ||
31 | #include <asm/io.h> | 31 | #include <asm/io.h> |
32 | #include <asm/machdep.h> | 32 | #include <asm/machdep.h> |
33 | #include <asm/rtas.h> | ||
34 | #include <asm/atomic.h> | ||
35 | #include <asm/systemcfg.h> | ||
36 | #include <asm/ppc-pci.h> | 33 | #include <asm/ppc-pci.h> |
34 | #include <asm/rtas.h> | ||
37 | 35 | ||
38 | #undef DEBUG | 36 | #undef DEBUG |
39 | 37 | ||
@@ -49,8 +47,8 @@ | |||
49 | * were "empty": all reads return 0xff's and all writes are silently | 47 | * were "empty": all reads return 0xff's and all writes are silently |
50 | * ignored. EEH slot isolation events can be triggered by parity | 48 | * ignored. EEH slot isolation events can be triggered by parity |
51 | * errors on the address or data busses (e.g. during posted writes), | 49 | * errors on the address or data busses (e.g. during posted writes), |
52 | * which in turn might be caused by dust, vibration, humidity, | 50 | * which in turn might be caused by low voltage on the bus, dust, |
53 | * radioactivity or plain-old failed hardware. | 51 | * vibration, humidity, radioactivity or plain-old failed hardware. |
54 | * | 52 | * |
55 | * Note, however, that one of the leading causes of EEH slot | 53 | * Note, however, that one of the leading causes of EEH slot |
56 | * freeze events are buggy device drivers, buggy device microcode, | 54 | * freeze events are buggy device drivers, buggy device microcode, |
@@ -71,26 +69,15 @@ | |||
71 | * and sent out for processing. | 69 | * and sent out for processing. |
72 | */ | 70 | */ |
73 | 71 | ||
74 | /** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */ | 72 | /* If a device driver keeps reading an MMIO register in an interrupt |
75 | #define BUID_HI(buid) ((buid) >> 32) | ||
76 | #define BUID_LO(buid) ((buid) & 0xffffffff) | ||
77 | |||
78 | /* EEH event workqueue setup. */ | ||
79 | static DEFINE_SPINLOCK(eeh_eventlist_lock); | ||
80 | LIST_HEAD(eeh_eventlist); | ||
81 | static void eeh_event_handler(void *); | ||
82 | DECLARE_WORK(eeh_event_wq, eeh_event_handler, NULL); | ||
83 | |||
84 | static struct notifier_block *eeh_notifier_chain; | ||
85 | |||
86 | /* | ||
87 | * If a device driver keeps reading an MMIO register in an interrupt | ||
88 | * handler after a slot isolation event has occurred, we assume it | 73 | * handler after a slot isolation event has occurred, we assume it |
89 | * is broken and panic. This sets the threshold for how many read | 74 | * is broken and panic. This sets the threshold for how many read |
90 | * attempts we allow before panicking. | 75 | * attempts we allow before panicking. |
91 | */ | 76 | */ |
92 | #define EEH_MAX_FAILS 1000 | 77 | #define EEH_MAX_FAILS 100000 |
93 | static atomic_t eeh_fail_count; | 78 | |
79 | /* Misc forward declaraions */ | ||
80 | static void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn); | ||
94 | 81 | ||
95 | /* RTAS tokens */ | 82 | /* RTAS tokens */ |
96 | static int ibm_set_eeh_option; | 83 | static int ibm_set_eeh_option; |
@@ -101,12 +88,19 @@ static int ibm_slot_error_detail; | |||
101 | 88 | ||
102 | static int eeh_subsystem_enabled; | 89 | static int eeh_subsystem_enabled; |
103 | 90 | ||
91 | /* Lock to avoid races due to multiple reports of an error */ | ||
92 | static DEFINE_SPINLOCK(confirm_error_lock); | ||
93 | |||
104 | /* Buffer for reporting slot-error-detail rtas calls */ | 94 | /* Buffer for reporting slot-error-detail rtas calls */ |
105 | static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX]; | 95 | static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX]; |
106 | static DEFINE_SPINLOCK(slot_errbuf_lock); | 96 | static DEFINE_SPINLOCK(slot_errbuf_lock); |
107 | static int eeh_error_buf_size; | 97 | static int eeh_error_buf_size; |
108 | 98 | ||
109 | /* System monitoring statistics */ | 99 | /* System monitoring statistics */ |
100 | static DEFINE_PER_CPU(unsigned long, no_device); | ||
101 | static DEFINE_PER_CPU(unsigned long, no_dn); | ||
102 | static DEFINE_PER_CPU(unsigned long, no_cfg_addr); | ||
103 | static DEFINE_PER_CPU(unsigned long, ignored_check); | ||
110 | static DEFINE_PER_CPU(unsigned long, total_mmio_ffs); | 104 | static DEFINE_PER_CPU(unsigned long, total_mmio_ffs); |
111 | static DEFINE_PER_CPU(unsigned long, false_positives); | 105 | static DEFINE_PER_CPU(unsigned long, false_positives); |
112 | static DEFINE_PER_CPU(unsigned long, ignored_failures); | 106 | static DEFINE_PER_CPU(unsigned long, ignored_failures); |
@@ -224,9 +218,9 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo, | |||
224 | while (*p) { | 218 | while (*p) { |
225 | parent = *p; | 219 | parent = *p; |
226 | piar = rb_entry(parent, struct pci_io_addr_range, rb_node); | 220 | piar = rb_entry(parent, struct pci_io_addr_range, rb_node); |
227 | if (alo < piar->addr_lo) { | 221 | if (ahi < piar->addr_lo) { |
228 | p = &parent->rb_left; | 222 | p = &parent->rb_left; |
229 | } else if (ahi > piar->addr_hi) { | 223 | } else if (alo > piar->addr_hi) { |
230 | p = &parent->rb_right; | 224 | p = &parent->rb_right; |
231 | } else { | 225 | } else { |
232 | if (dev != piar->pcidev || | 226 | if (dev != piar->pcidev || |
@@ -245,6 +239,11 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo, | |||
245 | piar->pcidev = dev; | 239 | piar->pcidev = dev; |
246 | piar->flags = flags; | 240 | piar->flags = flags; |
247 | 241 | ||
242 | #ifdef DEBUG | ||
243 | printk(KERN_DEBUG "PIAR: insert range=[%lx:%lx] dev=%s\n", | ||
244 | alo, ahi, pci_name (dev)); | ||
245 | #endif | ||
246 | |||
248 | rb_link_node(&piar->rb_node, parent, p); | 247 | rb_link_node(&piar->rb_node, parent, p); |
249 | rb_insert_color(&piar->rb_node, &pci_io_addr_cache_root.rb_root); | 248 | rb_insert_color(&piar->rb_node, &pci_io_addr_cache_root.rb_root); |
250 | 249 | ||
@@ -260,18 +259,17 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev) | |||
260 | 259 | ||
261 | dn = pci_device_to_OF_node(dev); | 260 | dn = pci_device_to_OF_node(dev); |
262 | if (!dn) { | 261 | if (!dn) { |
263 | printk(KERN_WARNING "PCI: no pci dn found for dev=%s\n", | 262 | printk(KERN_WARNING "PCI: no pci dn found for dev=%s\n", pci_name(dev)); |
264 | pci_name(dev)); | ||
265 | return; | 263 | return; |
266 | } | 264 | } |
267 | 265 | ||
268 | /* Skip any devices for which EEH is not enabled. */ | 266 | /* Skip any devices for which EEH is not enabled. */ |
269 | pdn = dn->data; | 267 | pdn = PCI_DN(dn); |
270 | if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) || | 268 | if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) || |
271 | pdn->eeh_mode & EEH_MODE_NOCHECK) { | 269 | pdn->eeh_mode & EEH_MODE_NOCHECK) { |
272 | #ifdef DEBUG | 270 | #ifdef DEBUG |
273 | printk(KERN_INFO "PCI: skip building address cache for=%s\n", | 271 | printk(KERN_INFO "PCI: skip building address cache for=%s - %s\n", |
274 | pci_name(dev)); | 272 | pci_name(dev), pdn->node->full_name); |
275 | #endif | 273 | #endif |
276 | return; | 274 | return; |
277 | } | 275 | } |
@@ -307,7 +305,7 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev) | |||
307 | * we maintain a cache of devices that can be quickly searched. | 305 | * we maintain a cache of devices that can be quickly searched. |
308 | * This routine adds a device to that cache. | 306 | * This routine adds a device to that cache. |
309 | */ | 307 | */ |
310 | void pci_addr_cache_insert_device(struct pci_dev *dev) | 308 | static void pci_addr_cache_insert_device(struct pci_dev *dev) |
311 | { | 309 | { |
312 | unsigned long flags; | 310 | unsigned long flags; |
313 | 311 | ||
@@ -350,7 +348,7 @@ restart: | |||
350 | * the tree multiple times (once per resource). | 348 | * the tree multiple times (once per resource). |
351 | * But so what; device removal doesn't need to be that fast. | 349 | * But so what; device removal doesn't need to be that fast. |
352 | */ | 350 | */ |
353 | void pci_addr_cache_remove_device(struct pci_dev *dev) | 351 | static void pci_addr_cache_remove_device(struct pci_dev *dev) |
354 | { | 352 | { |
355 | unsigned long flags; | 353 | unsigned long flags; |
356 | 354 | ||
@@ -370,8 +368,12 @@ void pci_addr_cache_remove_device(struct pci_dev *dev) | |||
370 | */ | 368 | */ |
371 | void __init pci_addr_cache_build(void) | 369 | void __init pci_addr_cache_build(void) |
372 | { | 370 | { |
371 | struct device_node *dn; | ||
373 | struct pci_dev *dev = NULL; | 372 | struct pci_dev *dev = NULL; |
374 | 373 | ||
374 | if (!eeh_subsystem_enabled) | ||
375 | return; | ||
376 | |||
375 | spin_lock_init(&pci_io_addr_cache_root.piar_lock); | 377 | spin_lock_init(&pci_io_addr_cache_root.piar_lock); |
376 | 378 | ||
377 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | 379 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { |
@@ -380,6 +382,10 @@ void __init pci_addr_cache_build(void) | |||
380 | continue; | 382 | continue; |
381 | } | 383 | } |
382 | pci_addr_cache_insert_device(dev); | 384 | pci_addr_cache_insert_device(dev); |
385 | |||
386 | /* Save the BAR's; firmware doesn't restore these after EEH reset */ | ||
387 | dn = pci_device_to_OF_node(dev); | ||
388 | eeh_save_bars(dev, PCI_DN(dn)); | ||
383 | } | 389 | } |
384 | 390 | ||
385 | #ifdef DEBUG | 391 | #ifdef DEBUG |
@@ -391,22 +397,26 @@ void __init pci_addr_cache_build(void) | |||
391 | /* --------------------------------------------------------------- */ | 397 | /* --------------------------------------------------------------- */ |
392 | /* Above lies the PCI Address Cache. Below lies the EEH event infrastructure */ | 398 | /* Above lies the PCI Address Cache. Below lies the EEH event infrastructure */ |
393 | 399 | ||
394 | /** | 400 | void eeh_slot_error_detail (struct pci_dn *pdn, int severity) |
395 | * eeh_register_notifier - Register to find out about EEH events. | ||
396 | * @nb: notifier block to callback on events | ||
397 | */ | ||
398 | int eeh_register_notifier(struct notifier_block *nb) | ||
399 | { | 401 | { |
400 | return notifier_chain_register(&eeh_notifier_chain, nb); | 402 | unsigned long flags; |
401 | } | 403 | int rc; |
402 | 404 | ||
403 | /** | 405 | /* Log the error with the rtas logger */ |
404 | * eeh_unregister_notifier - Unregister to an EEH event notifier. | 406 | spin_lock_irqsave(&slot_errbuf_lock, flags); |
405 | * @nb: notifier block to callback on events | 407 | memset(slot_errbuf, 0, eeh_error_buf_size); |
406 | */ | 408 | |
407 | int eeh_unregister_notifier(struct notifier_block *nb) | 409 | rc = rtas_call(ibm_slot_error_detail, |
408 | { | 410 | 8, 1, NULL, pdn->eeh_config_addr, |
409 | return notifier_chain_unregister(&eeh_notifier_chain, nb); | 411 | BUID_HI(pdn->phb->buid), |
412 | BUID_LO(pdn->phb->buid), NULL, 0, | ||
413 | virt_to_phys(slot_errbuf), | ||
414 | eeh_error_buf_size, | ||
415 | severity); | ||
416 | |||
417 | if (rc == 0) | ||
418 | log_error(slot_errbuf, ERR_TYPE_RTAS_LOG, 0); | ||
419 | spin_unlock_irqrestore(&slot_errbuf_lock, flags); | ||
410 | } | 420 | } |
411 | 421 | ||
412 | /** | 422 | /** |
@@ -414,16 +424,16 @@ int eeh_unregister_notifier(struct notifier_block *nb) | |||
414 | * @dn: device node to read | 424 | * @dn: device node to read |
415 | * @rets: array to return results in | 425 | * @rets: array to return results in |
416 | */ | 426 | */ |
417 | static int read_slot_reset_state(struct device_node *dn, int rets[]) | 427 | static int read_slot_reset_state(struct pci_dn *pdn, int rets[]) |
418 | { | 428 | { |
419 | int token, outputs; | 429 | int token, outputs; |
420 | struct pci_dn *pdn = dn->data; | ||
421 | 430 | ||
422 | if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) { | 431 | if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) { |
423 | token = ibm_read_slot_reset_state2; | 432 | token = ibm_read_slot_reset_state2; |
424 | outputs = 4; | 433 | outputs = 4; |
425 | } else { | 434 | } else { |
426 | token = ibm_read_slot_reset_state; | 435 | token = ibm_read_slot_reset_state; |
436 | rets[2] = 0; /* fake PE Unavailable info */ | ||
427 | outputs = 3; | 437 | outputs = 3; |
428 | } | 438 | } |
429 | 439 | ||
@@ -432,87 +442,84 @@ static int read_slot_reset_state(struct device_node *dn, int rets[]) | |||
432 | } | 442 | } |
433 | 443 | ||
434 | /** | 444 | /** |
435 | * eeh_panic - call panic() for an eeh event that cannot be handled. | 445 | * eeh_token_to_phys - convert EEH address token to phys address |
436 | * The philosophy of this routine is that it is better to panic and | 446 | * @token i/o token, should be address in the form 0xA.... |
437 | * halt the OS than it is to risk possible data corruption by | ||
438 | * oblivious device drivers that don't know better. | ||
439 | * | ||
440 | * @dev pci device that had an eeh event | ||
441 | * @reset_state current reset state of the device slot | ||
442 | */ | 447 | */ |
443 | static void eeh_panic(struct pci_dev *dev, int reset_state) | 448 | static inline unsigned long eeh_token_to_phys(unsigned long token) |
444 | { | 449 | { |
445 | /* | 450 | pte_t *ptep; |
446 | * XXX We should create a separate sysctl for this. | 451 | unsigned long pa; |
447 | * | 452 | |
448 | * Since the panic_on_oops sysctl is used to halt the system | 453 | ptep = find_linux_pte(init_mm.pgd, token); |
449 | * in light of potential corruption, we can use it here. | 454 | if (!ptep) |
450 | */ | 455 | return token; |
451 | if (panic_on_oops) | 456 | pa = pte_pfn(*ptep) << PAGE_SHIFT; |
452 | panic("EEH: MMIO failure (%d) on device:%s\n", reset_state, | 457 | |
453 | pci_name(dev)); | 458 | return pa | (token & (PAGE_SIZE-1)); |
454 | else { | ||
455 | __get_cpu_var(ignored_failures)++; | ||
456 | printk(KERN_INFO "EEH: Ignored MMIO failure (%d) on device:%s\n", | ||
457 | reset_state, pci_name(dev)); | ||
458 | } | ||
459 | } | 459 | } |
460 | 460 | ||
461 | /** | 461 | /** |
462 | * eeh_event_handler - dispatch EEH events. The detection of a frozen | 462 | * Return the "partitionable endpoint" (pe) under which this device lies |
463 | * slot can occur inside an interrupt, where it can be hard to do | ||
464 | * anything about it. The goal of this routine is to pull these | ||
465 | * detection events out of the context of the interrupt handler, and | ||
466 | * re-dispatch them for processing at a later time in a normal context. | ||
467 | * | ||
468 | * @dummy - unused | ||
469 | */ | 463 | */ |
470 | static void eeh_event_handler(void *dummy) | 464 | static struct device_node * find_device_pe(struct device_node *dn) |
471 | { | 465 | { |
472 | unsigned long flags; | 466 | while ((dn->parent) && PCI_DN(dn->parent) && |
473 | struct eeh_event *event; | 467 | (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) { |
474 | 468 | dn = dn->parent; | |
475 | while (1) { | 469 | } |
476 | spin_lock_irqsave(&eeh_eventlist_lock, flags); | 470 | return dn; |
477 | event = NULL; | 471 | } |
478 | if (!list_empty(&eeh_eventlist)) { | ||
479 | event = list_entry(eeh_eventlist.next, struct eeh_event, list); | ||
480 | list_del(&event->list); | ||
481 | } | ||
482 | spin_unlock_irqrestore(&eeh_eventlist_lock, flags); | ||
483 | if (event == NULL) | ||
484 | break; | ||
485 | |||
486 | printk(KERN_INFO "EEH: MMIO failure (%d), notifiying device " | ||
487 | "%s\n", event->reset_state, | ||
488 | pci_name(event->dev)); | ||
489 | 472 | ||
490 | atomic_set(&eeh_fail_count, 0); | 473 | /** Mark all devices that are peers of this device as failed. |
491 | notifier_call_chain (&eeh_notifier_chain, | 474 | * Mark the device driver too, so that it can see the failure |
492 | EEH_NOTIFY_FREEZE, event); | 475 | * immediately; this is critical, since some drivers poll |
476 | * status registers in interrupts ... If a driver is polling, | ||
477 | * and the slot is frozen, then the driver can deadlock in | ||
478 | * an interrupt context, which is bad. | ||
479 | */ | ||
493 | 480 | ||
494 | __get_cpu_var(slot_resets)++; | 481 | static void __eeh_mark_slot (struct device_node *dn, int mode_flag) |
482 | { | ||
483 | while (dn) { | ||
484 | if (PCI_DN(dn)) { | ||
485 | PCI_DN(dn)->eeh_mode |= mode_flag; | ||
495 | 486 | ||
496 | pci_dev_put(event->dev); | 487 | if (dn->child) |
497 | kfree(event); | 488 | __eeh_mark_slot (dn->child, mode_flag); |
489 | } | ||
490 | dn = dn->sibling; | ||
498 | } | 491 | } |
499 | } | 492 | } |
500 | 493 | ||
501 | /** | 494 | void eeh_mark_slot (struct device_node *dn, int mode_flag) |
502 | * eeh_token_to_phys - convert EEH address token to phys address | ||
503 | * @token i/o token, should be address in the form 0xE.... | ||
504 | */ | ||
505 | static inline unsigned long eeh_token_to_phys(unsigned long token) | ||
506 | { | 495 | { |
507 | pte_t *ptep; | 496 | dn = find_device_pe (dn); |
508 | unsigned long pa; | 497 | PCI_DN(dn)->eeh_mode |= mode_flag; |
498 | __eeh_mark_slot (dn->child, mode_flag); | ||
499 | } | ||
509 | 500 | ||
510 | ptep = find_linux_pte(init_mm.pgd, token); | 501 | static void __eeh_clear_slot (struct device_node *dn, int mode_flag) |
511 | if (!ptep) | 502 | { |
512 | return token; | 503 | while (dn) { |
513 | pa = pte_pfn(*ptep) << PAGE_SHIFT; | 504 | if (PCI_DN(dn)) { |
505 | PCI_DN(dn)->eeh_mode &= ~mode_flag; | ||
506 | PCI_DN(dn)->eeh_check_count = 0; | ||
507 | if (dn->child) | ||
508 | __eeh_clear_slot (dn->child, mode_flag); | ||
509 | } | ||
510 | dn = dn->sibling; | ||
511 | } | ||
512 | } | ||
514 | 513 | ||
515 | return pa | (token & (PAGE_SIZE-1)); | 514 | void eeh_clear_slot (struct device_node *dn, int mode_flag) |
515 | { | ||
516 | unsigned long flags; | ||
517 | spin_lock_irqsave(&confirm_error_lock, flags); | ||
518 | dn = find_device_pe (dn); | ||
519 | PCI_DN(dn)->eeh_mode &= ~mode_flag; | ||
520 | PCI_DN(dn)->eeh_check_count = 0; | ||
521 | __eeh_clear_slot (dn->child, mode_flag); | ||
522 | spin_unlock_irqrestore(&confirm_error_lock, flags); | ||
516 | } | 523 | } |
517 | 524 | ||
518 | /** | 525 | /** |
@@ -526,7 +533,7 @@ static inline unsigned long eeh_token_to_phys(unsigned long token) | |||
526 | * will query firmware for the EEH status. | 533 | * will query firmware for the EEH status. |
527 | * | 534 | * |
528 | * Returns 0 if there has not been an EEH error; otherwise returns | 535 | * Returns 0 if there has not been an EEH error; otherwise returns |
529 | * a non-zero value and queues up a solt isolation event notification. | 536 | * a non-zero value and queues up a slot isolation event notification. |
530 | * | 537 | * |
531 | * It is safe to call this routine in an interrupt context. | 538 | * It is safe to call this routine in an interrupt context. |
532 | */ | 539 | */ |
@@ -535,42 +542,59 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
535 | int ret; | 542 | int ret; |
536 | int rets[3]; | 543 | int rets[3]; |
537 | unsigned long flags; | 544 | unsigned long flags; |
538 | int rc, reset_state; | ||
539 | struct eeh_event *event; | ||
540 | struct pci_dn *pdn; | 545 | struct pci_dn *pdn; |
546 | int rc = 0; | ||
541 | 547 | ||
542 | __get_cpu_var(total_mmio_ffs)++; | 548 | __get_cpu_var(total_mmio_ffs)++; |
543 | 549 | ||
544 | if (!eeh_subsystem_enabled) | 550 | if (!eeh_subsystem_enabled) |
545 | return 0; | 551 | return 0; |
546 | 552 | ||
547 | if (!dn) | 553 | if (!dn) { |
554 | __get_cpu_var(no_dn)++; | ||
548 | return 0; | 555 | return 0; |
549 | pdn = dn->data; | 556 | } |
557 | pdn = PCI_DN(dn); | ||
550 | 558 | ||
551 | /* Access to IO BARs might get this far and still not want checking. */ | 559 | /* Access to IO BARs might get this far and still not want checking. */ |
552 | if (!pdn->eeh_capable || !(pdn->eeh_mode & EEH_MODE_SUPPORTED) || | 560 | if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) || |
553 | pdn->eeh_mode & EEH_MODE_NOCHECK) { | 561 | pdn->eeh_mode & EEH_MODE_NOCHECK) { |
562 | __get_cpu_var(ignored_check)++; | ||
563 | #ifdef DEBUG | ||
564 | printk ("EEH:ignored check (%x) for %s %s\n", | ||
565 | pdn->eeh_mode, pci_name (dev), dn->full_name); | ||
566 | #endif | ||
554 | return 0; | 567 | return 0; |
555 | } | 568 | } |
556 | 569 | ||
557 | if (!pdn->eeh_config_addr) { | 570 | if (!pdn->eeh_config_addr) { |
571 | __get_cpu_var(no_cfg_addr)++; | ||
558 | return 0; | 572 | return 0; |
559 | } | 573 | } |
560 | 574 | ||
561 | /* | 575 | /* If we already have a pending isolation event for this |
562 | * If we already have a pending isolation event for this | 576 | * slot, we know it's bad already, we don't need to check. |
563 | * slot, we know it's bad already, we don't need to check... | 577 | * Do this checking under a lock; as multiple PCI devices |
578 | * in one slot might report errors simultaneously, and we | ||
579 | * only want one error recovery routine running. | ||
564 | */ | 580 | */ |
581 | spin_lock_irqsave(&confirm_error_lock, flags); | ||
582 | rc = 1; | ||
565 | if (pdn->eeh_mode & EEH_MODE_ISOLATED) { | 583 | if (pdn->eeh_mode & EEH_MODE_ISOLATED) { |
566 | atomic_inc(&eeh_fail_count); | 584 | pdn->eeh_check_count ++; |
567 | if (atomic_read(&eeh_fail_count) >= EEH_MAX_FAILS) { | 585 | if (pdn->eeh_check_count >= EEH_MAX_FAILS) { |
586 | printk (KERN_ERR "EEH: Device driver ignored %d bad reads, panicing\n", | ||
587 | pdn->eeh_check_count); | ||
588 | dump_stack(); | ||
589 | |||
568 | /* re-read the slot reset state */ | 590 | /* re-read the slot reset state */ |
569 | if (read_slot_reset_state(dn, rets) != 0) | 591 | if (read_slot_reset_state(pdn, rets) != 0) |
570 | rets[0] = -1; /* reset state unknown */ | 592 | rets[0] = -1; /* reset state unknown */ |
571 | eeh_panic(dev, rets[0]); | 593 | |
594 | /* If we are here, then we hit an infinite loop. Stop. */ | ||
595 | panic("EEH: MMIO halt (%d) on device:%s\n", rets[0], pci_name(dev)); | ||
572 | } | 596 | } |
573 | return 0; | 597 | goto dn_unlock; |
574 | } | 598 | } |
575 | 599 | ||
576 | /* | 600 | /* |
@@ -580,66 +604,69 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
580 | * function zero of a multi-function device. | 604 | * function zero of a multi-function device. |
581 | * In any case they must share a common PHB. | 605 | * In any case they must share a common PHB. |
582 | */ | 606 | */ |
583 | ret = read_slot_reset_state(dn, rets); | 607 | ret = read_slot_reset_state(pdn, rets); |
584 | if (!(ret == 0 && rets[1] == 1 && (rets[0] == 2 || rets[0] == 4))) { | 608 | |
609 | /* If the call to firmware failed, punt */ | ||
610 | if (ret != 0) { | ||
611 | printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n", | ||
612 | ret, dn->full_name); | ||
585 | __get_cpu_var(false_positives)++; | 613 | __get_cpu_var(false_positives)++; |
586 | return 0; | 614 | rc = 0; |
615 | goto dn_unlock; | ||
587 | } | 616 | } |
588 | 617 | ||
589 | /* prevent repeated reports of this failure */ | 618 | /* If EEH is not supported on this device, punt. */ |
590 | pdn->eeh_mode |= EEH_MODE_ISOLATED; | 619 | if (rets[1] != 1) { |
591 | 620 | printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", | |
592 | reset_state = rets[0]; | 621 | ret, dn->full_name); |
593 | 622 | __get_cpu_var(false_positives)++; | |
594 | spin_lock_irqsave(&slot_errbuf_lock, flags); | 623 | rc = 0; |
595 | memset(slot_errbuf, 0, eeh_error_buf_size); | 624 | goto dn_unlock; |
596 | 625 | } | |
597 | rc = rtas_call(ibm_slot_error_detail, | ||
598 | 8, 1, NULL, pdn->eeh_config_addr, | ||
599 | BUID_HI(pdn->phb->buid), | ||
600 | BUID_LO(pdn->phb->buid), NULL, 0, | ||
601 | virt_to_phys(slot_errbuf), | ||
602 | eeh_error_buf_size, | ||
603 | 1 /* Temporary Error */); | ||
604 | |||
605 | if (rc == 0) | ||
606 | log_error(slot_errbuf, ERR_TYPE_RTAS_LOG, 0); | ||
607 | spin_unlock_irqrestore(&slot_errbuf_lock, flags); | ||
608 | 626 | ||
609 | printk(KERN_INFO "EEH: MMIO failure (%d) on device: %s %s\n", | 627 | /* If not the kind of error we know about, punt. */ |
610 | rets[0], dn->name, dn->full_name); | 628 | if (rets[0] != 2 && rets[0] != 4 && rets[0] != 5) { |
611 | event = kmalloc(sizeof(*event), GFP_ATOMIC); | 629 | __get_cpu_var(false_positives)++; |
612 | if (event == NULL) { | 630 | rc = 0; |
613 | eeh_panic(dev, reset_state); | 631 | goto dn_unlock; |
614 | return 1; | 632 | } |
615 | } | ||
616 | 633 | ||
617 | event->dev = dev; | 634 | /* Note that config-io to empty slots may fail; |
618 | event->dn = dn; | 635 | * we recognize empty because they don't have children. */ |
619 | event->reset_state = reset_state; | 636 | if ((rets[0] == 5) && (dn->child == NULL)) { |
637 | __get_cpu_var(false_positives)++; | ||
638 | rc = 0; | ||
639 | goto dn_unlock; | ||
640 | } | ||
620 | 641 | ||
621 | /* We may or may not be called in an interrupt context */ | 642 | __get_cpu_var(slot_resets)++; |
622 | spin_lock_irqsave(&eeh_eventlist_lock, flags); | 643 | |
623 | list_add(&event->list, &eeh_eventlist); | 644 | /* Avoid repeated reports of this failure, including problems |
624 | spin_unlock_irqrestore(&eeh_eventlist_lock, flags); | 645 | * with other functions on this device, and functions under |
646 | * bridges. */ | ||
647 | eeh_mark_slot (dn, EEH_MODE_ISOLATED); | ||
648 | spin_unlock_irqrestore(&confirm_error_lock, flags); | ||
625 | 649 | ||
650 | eeh_send_failure_event (dn, dev, rets[0], rets[2]); | ||
651 | |||
626 | /* Most EEH events are due to device driver bugs. Having | 652 | /* Most EEH events are due to device driver bugs. Having |
627 | * a stack trace will help the device-driver authors figure | 653 | * a stack trace will help the device-driver authors figure |
628 | * out what happened. So print that out. */ | 654 | * out what happened. So print that out. */ |
629 | dump_stack(); | 655 | if (rets[0] != 5) dump_stack(); |
630 | schedule_work(&eeh_event_wq); | 656 | return 1; |
631 | 657 | ||
632 | return 0; | 658 | dn_unlock: |
659 | spin_unlock_irqrestore(&confirm_error_lock, flags); | ||
660 | return rc; | ||
633 | } | 661 | } |
634 | 662 | ||
635 | EXPORT_SYMBOL(eeh_dn_check_failure); | 663 | EXPORT_SYMBOL_GPL(eeh_dn_check_failure); |
636 | 664 | ||
637 | /** | 665 | /** |
638 | * eeh_check_failure - check if all 1's data is due to EEH slot freeze | 666 | * eeh_check_failure - check if all 1's data is due to EEH slot freeze |
639 | * @token i/o token, should be address in the form 0xA.... | 667 | * @token i/o token, should be address in the form 0xA.... |
640 | * @val value, should be all 1's (XXX why do we need this arg??) | 668 | * @val value, should be all 1's (XXX why do we need this arg??) |
641 | * | 669 | * |
642 | * Check for an eeh failure at the given token address. | ||
643 | * Check for an EEH failure at the given token address. Call this | 670 | * Check for an EEH failure at the given token address. Call this |
644 | * routine if the result of a read was all 0xff's and you want to | 671 | * routine if the result of a read was all 0xff's and you want to |
645 | * find out if this is due to an EEH slot freeze event. This routine | 672 | * find out if this is due to an EEH slot freeze event. This routine |
@@ -656,8 +683,10 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned lon | |||
656 | /* Finding the phys addr + pci device; this is pretty quick. */ | 683 | /* Finding the phys addr + pci device; this is pretty quick. */ |
657 | addr = eeh_token_to_phys((unsigned long __force) token); | 684 | addr = eeh_token_to_phys((unsigned long __force) token); |
658 | dev = pci_get_device_by_addr(addr); | 685 | dev = pci_get_device_by_addr(addr); |
659 | if (!dev) | 686 | if (!dev) { |
687 | __get_cpu_var(no_device)++; | ||
660 | return val; | 688 | return val; |
689 | } | ||
661 | 690 | ||
662 | dn = pci_device_to_OF_node(dev); | 691 | dn = pci_device_to_OF_node(dev); |
663 | eeh_dn_check_failure (dn, dev); | 692 | eeh_dn_check_failure (dn, dev); |
@@ -668,6 +697,217 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned lon | |||
668 | 697 | ||
669 | EXPORT_SYMBOL(eeh_check_failure); | 698 | EXPORT_SYMBOL(eeh_check_failure); |
670 | 699 | ||
700 | /* ------------------------------------------------------------- */ | ||
701 | /* The code below deals with error recovery */ | ||
702 | |||
703 | /** Return negative value if a permanent error, else return | ||
704 | * a number of milliseconds to wait until the PCI slot is | ||
705 | * ready to be used. | ||
706 | */ | ||
707 | static int | ||
708 | eeh_slot_availability(struct pci_dn *pdn) | ||
709 | { | ||
710 | int rc; | ||
711 | int rets[3]; | ||
712 | |||
713 | rc = read_slot_reset_state(pdn, rets); | ||
714 | |||
715 | if (rc) return rc; | ||
716 | |||
717 | if (rets[1] == 0) return -1; /* EEH is not supported */ | ||
718 | if (rets[0] == 0) return 0; /* Oll Korrect */ | ||
719 | if (rets[0] == 5) { | ||
720 | if (rets[2] == 0) return -1; /* permanently unavailable */ | ||
721 | return rets[2]; /* number of millisecs to wait */ | ||
722 | } | ||
723 | return -1; | ||
724 | } | ||
725 | |||
726 | /** rtas_pci_slot_reset raises/lowers the pci #RST line | ||
727 | * state: 1/0 to raise/lower the #RST | ||
728 | * | ||
729 | * Clear the EEH-frozen condition on a slot. This routine | ||
730 | * asserts the PCI #RST line if the 'state' argument is '1', | ||
731 | * and drops the #RST line if 'state is '0'. This routine is | ||
732 | * safe to call in an interrupt context. | ||
733 | * | ||
734 | */ | ||
735 | |||
736 | static void | ||
737 | rtas_pci_slot_reset(struct pci_dn *pdn, int state) | ||
738 | { | ||
739 | int rc; | ||
740 | |||
741 | BUG_ON (pdn==NULL); | ||
742 | |||
743 | if (!pdn->phb) { | ||
744 | printk (KERN_WARNING "EEH: in slot reset, device node %s has no phb\n", | ||
745 | pdn->node->full_name); | ||
746 | return; | ||
747 | } | ||
748 | |||
749 | rc = rtas_call(ibm_set_slot_reset,4,1, NULL, | ||
750 | pdn->eeh_config_addr, | ||
751 | BUID_HI(pdn->phb->buid), | ||
752 | BUID_LO(pdn->phb->buid), | ||
753 | state); | ||
754 | if (rc) { | ||
755 | printk (KERN_WARNING "EEH: Unable to reset the failed slot, (%d) #RST=%d dn=%s\n", | ||
756 | rc, state, pdn->node->full_name); | ||
757 | return; | ||
758 | } | ||
759 | } | ||
760 | |||
761 | /** rtas_set_slot_reset -- assert the pci #RST line for 1/4 second | ||
762 | * dn -- device node to be reset. | ||
763 | */ | ||
764 | |||
765 | void | ||
766 | rtas_set_slot_reset(struct pci_dn *pdn) | ||
767 | { | ||
768 | int i, rc; | ||
769 | |||
770 | rtas_pci_slot_reset (pdn, 1); | ||
771 | |||
772 | /* The PCI bus requires that the reset be held high for at least | ||
773 | * a 100 milliseconds. We wait a bit longer 'just in case'. */ | ||
774 | |||
775 | #define PCI_BUS_RST_HOLD_TIME_MSEC 250 | ||
776 | msleep (PCI_BUS_RST_HOLD_TIME_MSEC); | ||
777 | |||
778 | /* We might get hit with another EEH freeze as soon as the | ||
779 | * pci slot reset line is dropped. Make sure we don't miss | ||
780 | * these, and clear the flag now. */ | ||
781 | eeh_clear_slot (pdn->node, EEH_MODE_ISOLATED); | ||
782 | |||
783 | rtas_pci_slot_reset (pdn, 0); | ||
784 | |||
785 | /* After a PCI slot has been reset, the PCI Express spec requires | ||
786 | * a 1.5 second idle time for the bus to stabilize, before starting | ||
787 | * up traffic. */ | ||
788 | #define PCI_BUS_SETTLE_TIME_MSEC 1800 | ||
789 | msleep (PCI_BUS_SETTLE_TIME_MSEC); | ||
790 | |||
791 | /* Now double check with the firmware to make sure the device is | ||
792 | * ready to be used; if not, wait for recovery. */ | ||
793 | for (i=0; i<10; i++) { | ||
794 | rc = eeh_slot_availability (pdn); | ||
795 | if (rc <= 0) break; | ||
796 | |||
797 | msleep (rc+100); | ||
798 | } | ||
799 | } | ||
800 | |||
801 | /* ------------------------------------------------------- */ | ||
802 | /** Save and restore of PCI BARs | ||
803 | * | ||
804 | * Although firmware will set up BARs during boot, it doesn't | ||
805 | * set up device BAR's after a device reset, although it will, | ||
806 | * if requested, set up bridge configuration. Thus, we need to | ||
807 | * configure the PCI devices ourselves. | ||
808 | */ | ||
809 | |||
810 | /** | ||
811 | * __restore_bars - Restore the Base Address Registers | ||
812 | * Loads the PCI configuration space base address registers, | ||
813 | * the expansion ROM base address, the latency timer, and etc. | ||
814 | * from the saved values in the device node. | ||
815 | */ | ||
816 | static inline void __restore_bars (struct pci_dn *pdn) | ||
817 | { | ||
818 | int i; | ||
819 | |||
820 | if (NULL==pdn->phb) return; | ||
821 | for (i=4; i<10; i++) { | ||
822 | rtas_write_config(pdn, i*4, 4, pdn->config_space[i]); | ||
823 | } | ||
824 | |||
825 | /* 12 == Expansion ROM Address */ | ||
826 | rtas_write_config(pdn, 12*4, 4, pdn->config_space[12]); | ||
827 | |||
828 | #define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF)) | ||
829 | #define SAVED_BYTE(OFF) (((u8 *)(pdn->config_space))[BYTE_SWAP(OFF)]) | ||
830 | |||
831 | rtas_write_config (pdn, PCI_CACHE_LINE_SIZE, 1, | ||
832 | SAVED_BYTE(PCI_CACHE_LINE_SIZE)); | ||
833 | |||
834 | rtas_write_config (pdn, PCI_LATENCY_TIMER, 1, | ||
835 | SAVED_BYTE(PCI_LATENCY_TIMER)); | ||
836 | |||
837 | /* max latency, min grant, interrupt pin and line */ | ||
838 | rtas_write_config(pdn, 15*4, 4, pdn->config_space[15]); | ||
839 | } | ||
840 | |||
841 | /** | ||
842 | * eeh_restore_bars - restore the PCI config space info | ||
843 | * | ||
844 | * This routine performs a recursive walk to the children | ||
845 | * of this device as well. | ||
846 | */ | ||
847 | void eeh_restore_bars(struct pci_dn *pdn) | ||
848 | { | ||
849 | struct device_node *dn; | ||
850 | if (!pdn) | ||
851 | return; | ||
852 | |||
853 | if (! pdn->eeh_is_bridge) | ||
854 | __restore_bars (pdn); | ||
855 | |||
856 | dn = pdn->node->child; | ||
857 | while (dn) { | ||
858 | eeh_restore_bars (PCI_DN(dn)); | ||
859 | dn = dn->sibling; | ||
860 | } | ||
861 | } | ||
862 | |||
863 | /** | ||
864 | * eeh_save_bars - save device bars | ||
865 | * | ||
866 | * Save the values of the device bars. Unlike the restore | ||
867 | * routine, this routine is *not* recursive. This is because | ||
868 | * PCI devices are added individuallly; but, for the restore, | ||
869 | * an entire slot is reset at a time. | ||
870 | */ | ||
871 | static void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn) | ||
872 | { | ||
873 | int i; | ||
874 | |||
875 | if (!pdev || !pdn ) | ||
876 | return; | ||
877 | |||
878 | for (i = 0; i < 16; i++) | ||
879 | pci_read_config_dword(pdev, i * 4, &pdn->config_space[i]); | ||
880 | |||
881 | if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE) | ||
882 | pdn->eeh_is_bridge = 1; | ||
883 | } | ||
884 | |||
885 | void | ||
886 | rtas_configure_bridge(struct pci_dn *pdn) | ||
887 | { | ||
888 | int token = rtas_token ("ibm,configure-bridge"); | ||
889 | int rc; | ||
890 | |||
891 | if (token == RTAS_UNKNOWN_SERVICE) | ||
892 | return; | ||
893 | rc = rtas_call(token,3,1, NULL, | ||
894 | pdn->eeh_config_addr, | ||
895 | BUID_HI(pdn->phb->buid), | ||
896 | BUID_LO(pdn->phb->buid)); | ||
897 | if (rc) { | ||
898 | printk (KERN_WARNING "EEH: Unable to configure device bridge (%d) for %s\n", | ||
899 | rc, pdn->node->full_name); | ||
900 | } | ||
901 | } | ||
902 | |||
903 | /* ------------------------------------------------------------- */ | ||
904 | /* The code below deals with enabling EEH for devices during the | ||
905 | * early boot sequence. EEH must be enabled before any PCI probing | ||
906 | * can be done. | ||
907 | */ | ||
908 | |||
909 | #define EEH_ENABLE 1 | ||
910 | |||
671 | struct eeh_early_enable_info { | 911 | struct eeh_early_enable_info { |
672 | unsigned int buid_hi; | 912 | unsigned int buid_hi; |
673 | unsigned int buid_lo; | 913 | unsigned int buid_lo; |
@@ -684,9 +924,11 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
684 | u32 *device_id = (u32 *)get_property(dn, "device-id", NULL); | 924 | u32 *device_id = (u32 *)get_property(dn, "device-id", NULL); |
685 | u32 *regs; | 925 | u32 *regs; |
686 | int enable; | 926 | int enable; |
687 | struct pci_dn *pdn = dn->data; | 927 | struct pci_dn *pdn = PCI_DN(dn); |
688 | 928 | ||
689 | pdn->eeh_mode = 0; | 929 | pdn->eeh_mode = 0; |
930 | pdn->eeh_check_count = 0; | ||
931 | pdn->eeh_freeze_count = 0; | ||
690 | 932 | ||
691 | if (status && strcmp(status, "ok") != 0) | 933 | if (status && strcmp(status, "ok") != 0) |
692 | return NULL; /* ignore devices with bad status */ | 934 | return NULL; /* ignore devices with bad status */ |
@@ -723,8 +965,9 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
723 | /* First register entry is addr (00BBSS00) */ | 965 | /* First register entry is addr (00BBSS00) */ |
724 | /* Try to enable eeh */ | 966 | /* Try to enable eeh */ |
725 | ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL, | 967 | ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL, |
726 | regs[0], info->buid_hi, info->buid_lo, | 968 | regs[0], info->buid_hi, info->buid_lo, |
727 | EEH_ENABLE); | 969 | EEH_ENABLE); |
970 | |||
728 | if (ret == 0) { | 971 | if (ret == 0) { |
729 | eeh_subsystem_enabled = 1; | 972 | eeh_subsystem_enabled = 1; |
730 | pdn->eeh_mode |= EEH_MODE_SUPPORTED; | 973 | pdn->eeh_mode |= EEH_MODE_SUPPORTED; |
@@ -736,7 +979,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
736 | 979 | ||
737 | /* This device doesn't support EEH, but it may have an | 980 | /* This device doesn't support EEH, but it may have an |
738 | * EEH parent, in which case we mark it as supported. */ | 981 | * EEH parent, in which case we mark it as supported. */ |
739 | if (dn->parent && dn->parent->data | 982 | if (dn->parent && PCI_DN(dn->parent) |
740 | && (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) { | 983 | && (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) { |
741 | /* Parent supports EEH. */ | 984 | /* Parent supports EEH. */ |
742 | pdn->eeh_mode |= EEH_MODE_SUPPORTED; | 985 | pdn->eeh_mode |= EEH_MODE_SUPPORTED; |
@@ -749,7 +992,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
749 | dn->full_name); | 992 | dn->full_name); |
750 | } | 993 | } |
751 | 994 | ||
752 | return NULL; | 995 | return NULL; |
753 | } | 996 | } |
754 | 997 | ||
755 | /* | 998 | /* |
@@ -770,6 +1013,9 @@ void __init eeh_init(void) | |||
770 | struct device_node *phb, *np; | 1013 | struct device_node *phb, *np; |
771 | struct eeh_early_enable_info info; | 1014 | struct eeh_early_enable_info info; |
772 | 1015 | ||
1016 | spin_lock_init(&confirm_error_lock); | ||
1017 | spin_lock_init(&slot_errbuf_lock); | ||
1018 | |||
773 | np = of_find_node_by_path("/rtas"); | 1019 | np = of_find_node_by_path("/rtas"); |
774 | if (np == NULL) | 1020 | if (np == NULL) |
775 | return; | 1021 | return; |
@@ -797,13 +1043,11 @@ void __init eeh_init(void) | |||
797 | for (phb = of_find_node_by_name(NULL, "pci"); phb; | 1043 | for (phb = of_find_node_by_name(NULL, "pci"); phb; |
798 | phb = of_find_node_by_name(phb, "pci")) { | 1044 | phb = of_find_node_by_name(phb, "pci")) { |
799 | unsigned long buid; | 1045 | unsigned long buid; |
800 | struct pci_dn *pci; | ||
801 | 1046 | ||
802 | buid = get_phb_buid(phb); | 1047 | buid = get_phb_buid(phb); |
803 | if (buid == 0 || phb->data == NULL) | 1048 | if (buid == 0 || PCI_DN(phb) == NULL) |
804 | continue; | 1049 | continue; |
805 | 1050 | ||
806 | pci = phb->data; | ||
807 | info.buid_lo = BUID_LO(buid); | 1051 | info.buid_lo = BUID_LO(buid); |
808 | info.buid_hi = BUID_HI(buid); | 1052 | info.buid_hi = BUID_HI(buid); |
809 | traverse_pci_devices(phb, early_enable_eeh, &info); | 1053 | traverse_pci_devices(phb, early_enable_eeh, &info); |
@@ -832,11 +1076,13 @@ void eeh_add_device_early(struct device_node *dn) | |||
832 | struct pci_controller *phb; | 1076 | struct pci_controller *phb; |
833 | struct eeh_early_enable_info info; | 1077 | struct eeh_early_enable_info info; |
834 | 1078 | ||
835 | if (!dn || !dn->data) | 1079 | if (!dn || !PCI_DN(dn)) |
836 | return; | 1080 | return; |
837 | phb = PCI_DN(dn)->phb; | 1081 | phb = PCI_DN(dn)->phb; |
838 | if (NULL == phb || 0 == phb->buid) { | 1082 | if (NULL == phb || 0 == phb->buid) { |
839 | printk(KERN_WARNING "EEH: Expected buid but found none\n"); | 1083 | printk(KERN_WARNING "EEH: Expected buid but found none for %s\n", |
1084 | dn->full_name); | ||
1085 | dump_stack(); | ||
840 | return; | 1086 | return; |
841 | } | 1087 | } |
842 | 1088 | ||
@@ -844,7 +1090,7 @@ void eeh_add_device_early(struct device_node *dn) | |||
844 | info.buid_lo = BUID_LO(phb->buid); | 1090 | info.buid_lo = BUID_LO(phb->buid); |
845 | early_enable_eeh(dn, &info); | 1091 | early_enable_eeh(dn, &info); |
846 | } | 1092 | } |
847 | EXPORT_SYMBOL(eeh_add_device_early); | 1093 | EXPORT_SYMBOL_GPL(eeh_add_device_early); |
848 | 1094 | ||
849 | /** | 1095 | /** |
850 | * eeh_add_device_late - perform EEH initialization for the indicated pci device | 1096 | * eeh_add_device_late - perform EEH initialization for the indicated pci device |
@@ -855,6 +1101,9 @@ EXPORT_SYMBOL(eeh_add_device_early); | |||
855 | */ | 1101 | */ |
856 | void eeh_add_device_late(struct pci_dev *dev) | 1102 | void eeh_add_device_late(struct pci_dev *dev) |
857 | { | 1103 | { |
1104 | struct device_node *dn; | ||
1105 | struct pci_dn *pdn; | ||
1106 | |||
858 | if (!dev || !eeh_subsystem_enabled) | 1107 | if (!dev || !eeh_subsystem_enabled) |
859 | return; | 1108 | return; |
860 | 1109 | ||
@@ -862,9 +1111,15 @@ void eeh_add_device_late(struct pci_dev *dev) | |||
862 | printk(KERN_DEBUG "EEH: adding device %s\n", pci_name(dev)); | 1111 | printk(KERN_DEBUG "EEH: adding device %s\n", pci_name(dev)); |
863 | #endif | 1112 | #endif |
864 | 1113 | ||
1114 | pci_dev_get (dev); | ||
1115 | dn = pci_device_to_OF_node(dev); | ||
1116 | pdn = PCI_DN(dn); | ||
1117 | pdn->pcidev = dev; | ||
1118 | |||
865 | pci_addr_cache_insert_device (dev); | 1119 | pci_addr_cache_insert_device (dev); |
1120 | eeh_save_bars(dev, pdn); | ||
866 | } | 1121 | } |
867 | EXPORT_SYMBOL(eeh_add_device_late); | 1122 | EXPORT_SYMBOL_GPL(eeh_add_device_late); |
868 | 1123 | ||
869 | /** | 1124 | /** |
870 | * eeh_remove_device - undo EEH setup for the indicated pci device | 1125 | * eeh_remove_device - undo EEH setup for the indicated pci device |
@@ -875,6 +1130,7 @@ EXPORT_SYMBOL(eeh_add_device_late); | |||
875 | */ | 1130 | */ |
876 | void eeh_remove_device(struct pci_dev *dev) | 1131 | void eeh_remove_device(struct pci_dev *dev) |
877 | { | 1132 | { |
1133 | struct device_node *dn; | ||
878 | if (!dev || !eeh_subsystem_enabled) | 1134 | if (!dev || !eeh_subsystem_enabled) |
879 | return; | 1135 | return; |
880 | 1136 | ||
@@ -883,20 +1139,29 @@ void eeh_remove_device(struct pci_dev *dev) | |||
883 | printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev)); | 1139 | printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev)); |
884 | #endif | 1140 | #endif |
885 | pci_addr_cache_remove_device(dev); | 1141 | pci_addr_cache_remove_device(dev); |
1142 | |||
1143 | dn = pci_device_to_OF_node(dev); | ||
1144 | PCI_DN(dn)->pcidev = NULL; | ||
1145 | pci_dev_put (dev); | ||
886 | } | 1146 | } |
887 | EXPORT_SYMBOL(eeh_remove_device); | 1147 | EXPORT_SYMBOL_GPL(eeh_remove_device); |
888 | 1148 | ||
889 | static int proc_eeh_show(struct seq_file *m, void *v) | 1149 | static int proc_eeh_show(struct seq_file *m, void *v) |
890 | { | 1150 | { |
891 | unsigned int cpu; | 1151 | unsigned int cpu; |
892 | unsigned long ffs = 0, positives = 0, failures = 0; | 1152 | unsigned long ffs = 0, positives = 0, failures = 0; |
893 | unsigned long resets = 0; | 1153 | unsigned long resets = 0; |
1154 | unsigned long no_dev = 0, no_dn = 0, no_cfg = 0, no_check = 0; | ||
894 | 1155 | ||
895 | for_each_cpu(cpu) { | 1156 | for_each_cpu(cpu) { |
896 | ffs += per_cpu(total_mmio_ffs, cpu); | 1157 | ffs += per_cpu(total_mmio_ffs, cpu); |
897 | positives += per_cpu(false_positives, cpu); | 1158 | positives += per_cpu(false_positives, cpu); |
898 | failures += per_cpu(ignored_failures, cpu); | 1159 | failures += per_cpu(ignored_failures, cpu); |
899 | resets += per_cpu(slot_resets, cpu); | 1160 | resets += per_cpu(slot_resets, cpu); |
1161 | no_dev += per_cpu(no_device, cpu); | ||
1162 | no_dn += per_cpu(no_dn, cpu); | ||
1163 | no_cfg += per_cpu(no_cfg_addr, cpu); | ||
1164 | no_check += per_cpu(ignored_check, cpu); | ||
900 | } | 1165 | } |
901 | 1166 | ||
902 | if (0 == eeh_subsystem_enabled) { | 1167 | if (0 == eeh_subsystem_enabled) { |
@@ -904,13 +1169,17 @@ static int proc_eeh_show(struct seq_file *m, void *v) | |||
904 | seq_printf(m, "eeh_total_mmio_ffs=%ld\n", ffs); | 1169 | seq_printf(m, "eeh_total_mmio_ffs=%ld\n", ffs); |
905 | } else { | 1170 | } else { |
906 | seq_printf(m, "EEH Subsystem is enabled\n"); | 1171 | seq_printf(m, "EEH Subsystem is enabled\n"); |
907 | seq_printf(m, "eeh_total_mmio_ffs=%ld\n" | 1172 | seq_printf(m, |
908 | "eeh_false_positives=%ld\n" | 1173 | "no device=%ld\n" |
909 | "eeh_ignored_failures=%ld\n" | 1174 | "no device node=%ld\n" |
910 | "eeh_slot_resets=%ld\n" | 1175 | "no config address=%ld\n" |
911 | "eeh_fail_count=%d\n", | 1176 | "check not wanted=%ld\n" |
912 | ffs, positives, failures, resets, | 1177 | "eeh_total_mmio_ffs=%ld\n" |
913 | eeh_fail_count.counter); | 1178 | "eeh_false_positives=%ld\n" |
1179 | "eeh_ignored_failures=%ld\n" | ||
1180 | "eeh_slot_resets=%ld\n", | ||
1181 | no_dev, no_dn, no_cfg, no_check, | ||
1182 | ffs, positives, failures, resets); | ||
914 | } | 1183 | } |
915 | 1184 | ||
916 | return 0; | 1185 | return 0; |
@@ -932,7 +1201,7 @@ static int __init eeh_init_proc(void) | |||
932 | { | 1201 | { |
933 | struct proc_dir_entry *e; | 1202 | struct proc_dir_entry *e; |
934 | 1203 | ||
935 | if (systemcfg->platform & PLATFORM_PSERIES) { | 1204 | if (platform_is_pseries()) { |
936 | e = create_proc_entry("ppc64/eeh", 0, NULL); | 1205 | e = create_proc_entry("ppc64/eeh", 0, NULL); |
937 | if (e) | 1206 | if (e) |
938 | e->proc_fops = &proc_eeh_operations; | 1207 | e->proc_fops = &proc_eeh_operations; |
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c new file mode 100644 index 000000000000..92497333c2b6 --- /dev/null +++ b/arch/powerpc/platforms/pseries/eeh_event.c | |||
@@ -0,0 +1,155 @@ | |||
1 | /* | ||
2 | * eeh_event.c | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | * | ||
18 | * Copyright (c) 2005 Linas Vepstas <linas@linas.org> | ||
19 | */ | ||
20 | |||
21 | #include <linux/list.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <asm/eeh_event.h> | ||
24 | |||
25 | /** Overview: | ||
26 | * EEH error states may be detected within exception handlers; | ||
27 | * however, the recovery processing needs to occur asynchronously | ||
28 | * in a normal kernel context and not an interrupt context. | ||
29 | * This pair of routines creates an event and queues it onto a | ||
30 | * work-queue, where a worker thread can drive recovery. | ||
31 | */ | ||
32 | |||
33 | /* EEH event workqueue setup. */ | ||
34 | static spinlock_t eeh_eventlist_lock = SPIN_LOCK_UNLOCKED; | ||
35 | LIST_HEAD(eeh_eventlist); | ||
36 | static void eeh_thread_launcher(void *); | ||
37 | DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL); | ||
38 | |||
39 | /** | ||
40 | * eeh_panic - call panic() for an eeh event that cannot be handled. | ||
41 | * The philosophy of this routine is that it is better to panic and | ||
42 | * halt the OS than it is to risk possible data corruption by | ||
43 | * oblivious device drivers that don't know better. | ||
44 | * | ||
45 | * @dev pci device that had an eeh event | ||
46 | * @reset_state current reset state of the device slot | ||
47 | */ | ||
48 | static void eeh_panic(struct pci_dev *dev, int reset_state) | ||
49 | { | ||
50 | /* | ||
51 | * Since the panic_on_oops sysctl is used to halt the system | ||
52 | * in light of potential corruption, we can use it here. | ||
53 | */ | ||
54 | if (panic_on_oops) { | ||
55 | panic("EEH: MMIO failure (%d) on device:%s\n", reset_state, | ||
56 | pci_name(dev)); | ||
57 | } | ||
58 | else { | ||
59 | printk(KERN_INFO "EEH: Ignored MMIO failure (%d) on device:%s\n", | ||
60 | reset_state, pci_name(dev)); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | /** | ||
65 | * eeh_event_handler - dispatch EEH events. The detection of a frozen | ||
66 | * slot can occur inside an interrupt, where it can be hard to do | ||
67 | * anything about it. The goal of this routine is to pull these | ||
68 | * detection events out of the context of the interrupt handler, and | ||
69 | * re-dispatch them for processing at a later time in a normal context. | ||
70 | * | ||
71 | * @dummy - unused | ||
72 | */ | ||
73 | static int eeh_event_handler(void * dummy) | ||
74 | { | ||
75 | unsigned long flags; | ||
76 | struct eeh_event *event; | ||
77 | |||
78 | daemonize ("eehd"); | ||
79 | |||
80 | while (1) { | ||
81 | set_current_state(TASK_INTERRUPTIBLE); | ||
82 | |||
83 | spin_lock_irqsave(&eeh_eventlist_lock, flags); | ||
84 | event = NULL; | ||
85 | if (!list_empty(&eeh_eventlist)) { | ||
86 | event = list_entry(eeh_eventlist.next, struct eeh_event, list); | ||
87 | list_del(&event->list); | ||
88 | } | ||
89 | spin_unlock_irqrestore(&eeh_eventlist_lock, flags); | ||
90 | if (event == NULL) | ||
91 | break; | ||
92 | |||
93 | printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n", | ||
94 | pci_name(event->dev)); | ||
95 | |||
96 | eeh_panic (event->dev, event->state); | ||
97 | |||
98 | kfree(event); | ||
99 | } | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | /** | ||
105 | * eeh_thread_launcher | ||
106 | * | ||
107 | * @dummy - unused | ||
108 | */ | ||
109 | static void eeh_thread_launcher(void *dummy) | ||
110 | { | ||
111 | if (kernel_thread(eeh_event_handler, NULL, CLONE_KERNEL) < 0) | ||
112 | printk(KERN_ERR "Failed to start EEH daemon\n"); | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * eeh_send_failure_event - generate a PCI error event | ||
117 | * @dev pci device | ||
118 | * | ||
119 | * This routine can be called within an interrupt context; | ||
120 | * the actual event will be delivered in a normal context | ||
121 | * (from a workqueue). | ||
122 | */ | ||
123 | int eeh_send_failure_event (struct device_node *dn, | ||
124 | struct pci_dev *dev, | ||
125 | int state, | ||
126 | int time_unavail) | ||
127 | { | ||
128 | unsigned long flags; | ||
129 | struct eeh_event *event; | ||
130 | |||
131 | event = kmalloc(sizeof(*event), GFP_ATOMIC); | ||
132 | if (event == NULL) { | ||
133 | printk (KERN_ERR "EEH: out of memory, event not handled\n"); | ||
134 | return 1; | ||
135 | } | ||
136 | |||
137 | if (dev) | ||
138 | pci_dev_get(dev); | ||
139 | |||
140 | event->dn = dn; | ||
141 | event->dev = dev; | ||
142 | event->state = state; | ||
143 | event->time_unavail = time_unavail; | ||
144 | |||
145 | /* We may or may not be called in an interrupt context */ | ||
146 | spin_lock_irqsave(&eeh_eventlist_lock, flags); | ||
147 | list_add(&event->list, &eeh_eventlist); | ||
148 | spin_unlock_irqrestore(&eeh_eventlist_lock, flags); | ||
149 | |||
150 | schedule_work(&eeh_event_wq); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | /********************** END OF FILE ******************************/ | ||
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index fcc50bfd43fd..97ba5214417f 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <asm/machdep.h> | 42 | #include <asm/machdep.h> |
43 | #include <asm/abs_addr.h> | 43 | #include <asm/abs_addr.h> |
44 | #include <asm/pSeries_reconfig.h> | 44 | #include <asm/pSeries_reconfig.h> |
45 | #include <asm/systemcfg.h> | ||
46 | #include <asm/firmware.h> | 45 | #include <asm/firmware.h> |
47 | #include <asm/tce.h> | 46 | #include <asm/tce.h> |
48 | #include <asm/ppc-pci.h> | 47 | #include <asm/ppc-pci.h> |
@@ -582,7 +581,7 @@ void iommu_init_early_pSeries(void) | |||
582 | return; | 581 | return; |
583 | } | 582 | } |
584 | 583 | ||
585 | if (systemcfg->platform & PLATFORM_LPAR) { | 584 | if (platform_is_lpar()) { |
586 | if (firmware_has_feature(FW_FEATURE_MULTITCE)) { | 585 | if (firmware_has_feature(FW_FEATURE_MULTITCE)) { |
587 | ppc_md.tce_build = tce_buildmulti_pSeriesLP; | 586 | ppc_md.tce_build = tce_buildmulti_pSeriesLP; |
588 | ppc_md.tce_free = tce_freemulti_pSeriesLP; | 587 | ppc_md.tce_free = tce_freemulti_pSeriesLP; |
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index c198656a3bb5..999a9620b5ce 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c | |||
@@ -107,7 +107,6 @@ static void __init pSeries_request_regions(void) | |||
107 | 107 | ||
108 | void __init pSeries_final_fixup(void) | 108 | void __init pSeries_final_fixup(void) |
109 | { | 109 | { |
110 | phbs_remap_io(); | ||
111 | pSeries_request_regions(); | 110 | pSeries_request_regions(); |
112 | 111 | ||
113 | pci_addr_cache_build(); | 112 | pci_addr_cache_build(); |
@@ -123,7 +122,7 @@ static void fixup_winbond_82c105(struct pci_dev* dev) | |||
123 | int i; | 122 | int i; |
124 | unsigned int reg; | 123 | unsigned int reg; |
125 | 124 | ||
126 | if (!(systemcfg->platform & PLATFORM_PSERIES)) | 125 | if (!platform_is_pseries()) |
127 | return; | 126 | return; |
128 | 127 | ||
129 | printk("Using INTC for W82c105 IDE controller.\n"); | 128 | printk("Using INTC for W82c105 IDE controller.\n"); |
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index d7d400339458..d8864164dbe8 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
@@ -408,7 +408,7 @@ static int proc_ppc64_create_ofdt(void) | |||
408 | { | 408 | { |
409 | struct proc_dir_entry *ent; | 409 | struct proc_dir_entry *ent; |
410 | 410 | ||
411 | if (!(systemcfg->platform & PLATFORM_PSERIES)) | 411 | if (!platform_is_pseries()) |
412 | return 0; | 412 | return 0; |
413 | 413 | ||
414 | ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL); | 414 | ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL); |
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index e26b0420b6dd..00cf331a1dc4 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c | |||
@@ -482,10 +482,12 @@ static int __init rtas_init(void) | |||
482 | { | 482 | { |
483 | struct proc_dir_entry *entry; | 483 | struct proc_dir_entry *entry; |
484 | 484 | ||
485 | /* No RTAS, only warn if we are on a pSeries box */ | 485 | if (!platform_is_pseries()) |
486 | return 0; | ||
487 | |||
488 | /* No RTAS */ | ||
486 | if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) { | 489 | if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) { |
487 | if (systemcfg->platform & PLATFORM_PSERIES) | 490 | printk(KERN_INFO "rtasd: no event-scan on system\n"); |
488 | printk(KERN_INFO "rtasd: no event-scan on system\n"); | ||
489 | return 1; | 491 | return 1; |
490 | } | 492 | } |
491 | 493 | ||
diff --git a/arch/ppc64/kernel/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c index 2edc947f7c44..2edc947f7c44 100644 --- a/arch/ppc64/kernel/scanlog.c +++ b/arch/powerpc/platforms/pseries/scanlog.c | |||
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index a093a0d4dd69..e94247c28d42 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -249,7 +249,7 @@ static void __init pSeries_setup_arch(void) | |||
249 | ppc_md.idle_loop = default_idle; | 249 | ppc_md.idle_loop = default_idle; |
250 | } | 250 | } |
251 | 251 | ||
252 | if (systemcfg->platform & PLATFORM_LPAR) | 252 | if (platform_is_lpar()) |
253 | ppc_md.enable_pmcs = pseries_lpar_enable_pmcs; | 253 | ppc_md.enable_pmcs = pseries_lpar_enable_pmcs; |
254 | else | 254 | else |
255 | ppc_md.enable_pmcs = power4_enable_pmcs; | 255 | ppc_md.enable_pmcs = power4_enable_pmcs; |
@@ -378,7 +378,7 @@ static void __init pSeries_init_early(void) | |||
378 | 378 | ||
379 | fw_feature_init(); | 379 | fw_feature_init(); |
380 | 380 | ||
381 | if (systemcfg->platform & PLATFORM_LPAR) | 381 | if (platform_is_lpar()) |
382 | hpte_init_lpar(); | 382 | hpte_init_lpar(); |
383 | else { | 383 | else { |
384 | hpte_init_native(); | 384 | hpte_init_native(); |
@@ -388,7 +388,7 @@ static void __init pSeries_init_early(void) | |||
388 | 388 | ||
389 | generic_find_legacy_serial_ports(&physport, &default_speed); | 389 | generic_find_legacy_serial_ports(&physport, &default_speed); |
390 | 390 | ||
391 | if (systemcfg->platform & PLATFORM_LPAR) | 391 | if (platform_is_lpar()) |
392 | find_udbg_vterm(); | 392 | find_udbg_vterm(); |
393 | else if (physport) { | 393 | else if (physport) { |
394 | /* Map the uart for udbg. */ | 394 | /* Map the uart for udbg. */ |
@@ -592,7 +592,7 @@ static void pseries_shared_idle(void) | |||
592 | 592 | ||
593 | static int pSeries_pci_probe_mode(struct pci_bus *bus) | 593 | static int pSeries_pci_probe_mode(struct pci_bus *bus) |
594 | { | 594 | { |
595 | if (systemcfg->platform & PLATFORM_LPAR) | 595 | if (platform_is_lpar()) |
596 | return PCI_PROBE_DEVTREE; | 596 | return PCI_PROBE_DEVTREE; |
597 | return PCI_PROBE_NORMAL; | 597 | return PCI_PROBE_NORMAL; |
598 | } | 598 | } |
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 7a243e8ccd7e..3ba794ca3288 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <asm/rtas.h> | 46 | #include <asm/rtas.h> |
47 | #include <asm/pSeries_reconfig.h> | 47 | #include <asm/pSeries_reconfig.h> |
48 | #include <asm/mpic.h> | 48 | #include <asm/mpic.h> |
49 | #include <asm/systemcfg.h> | ||
49 | 50 | ||
50 | #include "plpar_wrappers.h" | 51 | #include "plpar_wrappers.h" |
51 | 52 | ||
@@ -96,7 +97,7 @@ int pSeries_cpu_disable(void) | |||
96 | int cpu = smp_processor_id(); | 97 | int cpu = smp_processor_id(); |
97 | 98 | ||
98 | cpu_clear(cpu, cpu_online_map); | 99 | cpu_clear(cpu, cpu_online_map); |
99 | systemcfg->processorCount--; | 100 | _systemcfg->processorCount--; |
100 | 101 | ||
101 | /*fix boot_cpuid here*/ | 102 | /*fix boot_cpuid here*/ |
102 | if (cpu == boot_cpuid) | 103 | if (cpu == boot_cpuid) |
@@ -441,7 +442,7 @@ void __init smp_init_pSeries(void) | |||
441 | smp_ops->cpu_die = pSeries_cpu_die; | 442 | smp_ops->cpu_die = pSeries_cpu_die; |
442 | 443 | ||
443 | /* Processors can be added/removed only on LPAR */ | 444 | /* Processors can be added/removed only on LPAR */ |
444 | if (systemcfg->platform == PLATFORM_PSERIES_LPAR) | 445 | if (platform_is_lpar()) |
445 | pSeries_reconfig_notifier_register(&pSeries_smp_nb); | 446 | pSeries_reconfig_notifier_register(&pSeries_smp_nb); |
446 | #endif | 447 | #endif |
447 | 448 | ||
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index c72c86f05cb6..72ac18067ece 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
@@ -545,7 +545,9 @@ nextnode: | |||
545 | of_node_put(np); | 545 | of_node_put(np); |
546 | } | 546 | } |
547 | 547 | ||
548 | if (systemcfg->platform == PLATFORM_PSERIES) { | 548 | if (platform_is_lpar()) |
549 | ops = &pSeriesLP_ops; | ||
550 | else { | ||
549 | #ifdef CONFIG_SMP | 551 | #ifdef CONFIG_SMP |
550 | for_each_cpu(i) { | 552 | for_each_cpu(i) { |
551 | int hard_id; | 553 | int hard_id; |
@@ -561,12 +563,11 @@ nextnode: | |||
561 | #else | 563 | #else |
562 | xics_per_cpu[0] = ioremap(intr_base, intr_size); | 564 | xics_per_cpu[0] = ioremap(intr_base, intr_size); |
563 | #endif /* CONFIG_SMP */ | 565 | #endif /* CONFIG_SMP */ |
564 | } else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { | ||
565 | ops = &pSeriesLP_ops; | ||
566 | } | 566 | } |
567 | 567 | ||
568 | xics_8259_pic.enable = i8259_pic.enable; | 568 | xics_8259_pic.enable = i8259_pic.enable; |
569 | xics_8259_pic.disable = i8259_pic.disable; | 569 | xics_8259_pic.disable = i8259_pic.disable; |
570 | xics_8259_pic.end = i8259_pic.end; | ||
570 | for (i = 0; i < 16; ++i) | 571 | for (i = 0; i < 16; ++i) |
571 | get_irq_desc(i)->handler = &xics_8259_pic; | 572 | get_irq_desc(i)->handler = &xics_8259_pic; |
572 | for (; i < NR_IRQS; ++i) | 573 | for (; i < NR_IRQS; ++i) |
diff --git a/arch/powerpc/sysdev/u3_iommu.c b/arch/powerpc/sysdev/u3_iommu.c index 543d65909812..f32baf7f4693 100644 --- a/arch/powerpc/sysdev/u3_iommu.c +++ b/arch/powerpc/sysdev/u3_iommu.c | |||
@@ -226,7 +226,7 @@ static void iommu_table_u3_setup(void) | |||
226 | iommu_table_u3.it_busno = 0; | 226 | iommu_table_u3.it_busno = 0; |
227 | iommu_table_u3.it_offset = 0; | 227 | iommu_table_u3.it_offset = 0; |
228 | /* it_size is in number of entries */ | 228 | /* it_size is in number of entries */ |
229 | iommu_table_u3.it_size = dart_tablesize / sizeof(u32); | 229 | iommu_table_u3.it_size = (dart_tablesize / sizeof(u32)) >> DART_PAGE_FACTOR; |
230 | 230 | ||
231 | /* Initialize the common IOMMU code */ | 231 | /* Initialize the common IOMMU code */ |
232 | iommu_table_u3.it_base = (unsigned long)dart_vbase; | 232 | iommu_table_u3.it_base = (unsigned long)dart_vbase; |
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile index 79a784f0e7a9..b20312e5ed27 100644 --- a/arch/powerpc/xmon/Makefile +++ b/arch/powerpc/xmon/Makefile | |||
@@ -8,4 +8,4 @@ obj-$(CONFIG_8xx) += start_8xx.o | |||
8 | obj-$(CONFIG_6xx) += start_32.o | 8 | obj-$(CONFIG_6xx) += start_32.o |
9 | obj-$(CONFIG_4xx) += start_32.o | 9 | obj-$(CONFIG_4xx) += start_32.o |
10 | obj-$(CONFIG_PPC64) += start_64.o | 10 | obj-$(CONFIG_PPC64) += start_64.o |
11 | obj-y += xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o | 11 | obj-y += xmon.o ppc-dis.o ppc-opc.o setjmp.o nonstdio.o |
diff --git a/arch/powerpc/xmon/nonstdio.c b/arch/powerpc/xmon/nonstdio.c new file mode 100644 index 000000000000..78765833f4c0 --- /dev/null +++ b/arch/powerpc/xmon/nonstdio.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996-2005 Paul Mackerras. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | #include <linux/string.h> | ||
10 | #include <asm/time.h> | ||
11 | #include "nonstdio.h" | ||
12 | |||
13 | int xmon_putchar(int c) | ||
14 | { | ||
15 | char ch = c; | ||
16 | |||
17 | if (c == '\n') | ||
18 | xmon_putchar('\r'); | ||
19 | return xmon_write(&ch, 1) == 1? c: -1; | ||
20 | } | ||
21 | |||
22 | static char line[256]; | ||
23 | static char *lineptr; | ||
24 | static int lineleft; | ||
25 | |||
26 | int xmon_expect(const char *str, unsigned long timeout) | ||
27 | { | ||
28 | int c; | ||
29 | unsigned long t0; | ||
30 | |||
31 | /* assume 25MHz default timebase if tb_ticks_per_sec not set yet */ | ||
32 | timeout *= tb_ticks_per_sec? tb_ticks_per_sec: 25000000; | ||
33 | t0 = get_tbl(); | ||
34 | do { | ||
35 | lineptr = line; | ||
36 | for (;;) { | ||
37 | c = xmon_read_poll(); | ||
38 | if (c == -1) { | ||
39 | if (get_tbl() - t0 > timeout) | ||
40 | return 0; | ||
41 | continue; | ||
42 | } | ||
43 | if (c == '\n') | ||
44 | break; | ||
45 | if (c != '\r' && lineptr < &line[sizeof(line) - 1]) | ||
46 | *lineptr++ = c; | ||
47 | } | ||
48 | *lineptr = 0; | ||
49 | } while (strstr(line, str) == NULL); | ||
50 | return 1; | ||
51 | } | ||
52 | |||
53 | int xmon_getchar(void) | ||
54 | { | ||
55 | int c; | ||
56 | |||
57 | if (lineleft == 0) { | ||
58 | lineptr = line; | ||
59 | for (;;) { | ||
60 | c = xmon_readchar(); | ||
61 | if (c == -1 || c == 4) | ||
62 | break; | ||
63 | if (c == '\r' || c == '\n') { | ||
64 | *lineptr++ = '\n'; | ||
65 | xmon_putchar('\n'); | ||
66 | break; | ||
67 | } | ||
68 | switch (c) { | ||
69 | case 0177: | ||
70 | case '\b': | ||
71 | if (lineptr > line) { | ||
72 | xmon_putchar('\b'); | ||
73 | xmon_putchar(' '); | ||
74 | xmon_putchar('\b'); | ||
75 | --lineptr; | ||
76 | } | ||
77 | break; | ||
78 | case 'U' & 0x1F: | ||
79 | while (lineptr > line) { | ||
80 | xmon_putchar('\b'); | ||
81 | xmon_putchar(' '); | ||
82 | xmon_putchar('\b'); | ||
83 | --lineptr; | ||
84 | } | ||
85 | break; | ||
86 | default: | ||
87 | if (lineptr >= &line[sizeof(line) - 1]) | ||
88 | xmon_putchar('\a'); | ||
89 | else { | ||
90 | xmon_putchar(c); | ||
91 | *lineptr++ = c; | ||
92 | } | ||
93 | } | ||
94 | } | ||
95 | lineleft = lineptr - line; | ||
96 | lineptr = line; | ||
97 | } | ||
98 | if (lineleft == 0) | ||
99 | return -1; | ||
100 | --lineleft; | ||
101 | return *lineptr++; | ||
102 | } | ||
103 | |||
104 | char *xmon_gets(char *str, int nb) | ||
105 | { | ||
106 | char *p; | ||
107 | int c; | ||
108 | |||
109 | for (p = str; p < str + nb - 1; ) { | ||
110 | c = xmon_getchar(); | ||
111 | if (c == -1) { | ||
112 | if (p == str) | ||
113 | return NULL; | ||
114 | break; | ||
115 | } | ||
116 | *p++ = c; | ||
117 | if (c == '\n') | ||
118 | break; | ||
119 | } | ||
120 | *p = 0; | ||
121 | return str; | ||
122 | } | ||
123 | |||
124 | void xmon_printf(const char *format, ...) | ||
125 | { | ||
126 | va_list args; | ||
127 | int n; | ||
128 | static char xmon_outbuf[1024]; | ||
129 | |||
130 | va_start(args, format); | ||
131 | n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args); | ||
132 | va_end(args); | ||
133 | xmon_write(xmon_outbuf, n); | ||
134 | } | ||
diff --git a/arch/powerpc/xmon/nonstdio.h b/arch/powerpc/xmon/nonstdio.h index 84211a21c6f4..47cebbd2b1b1 100644 --- a/arch/powerpc/xmon/nonstdio.h +++ b/arch/powerpc/xmon/nonstdio.h | |||
@@ -1,22 +1,14 @@ | |||
1 | typedef int FILE; | ||
2 | extern FILE *xmon_stdin, *xmon_stdout; | ||
3 | #define EOF (-1) | 1 | #define EOF (-1) |
4 | #define stdin xmon_stdin | 2 | |
5 | #define stdout xmon_stdout | ||
6 | #define printf xmon_printf | 3 | #define printf xmon_printf |
7 | #define fprintf xmon_fprintf | ||
8 | #define fputs xmon_fputs | ||
9 | #define fgets xmon_fgets | ||
10 | #define putchar xmon_putchar | 4 | #define putchar xmon_putchar |
11 | #define getchar xmon_getchar | ||
12 | #define putc xmon_putc | ||
13 | #define getc xmon_getc | ||
14 | #define fopen(n, m) NULL | ||
15 | #define fflush(f) do {} while (0) | ||
16 | #define fclose(f) do {} while (0) | ||
17 | extern char *fgets(char *, int, void *); | ||
18 | extern void xmon_printf(const char *, ...); | ||
19 | extern void xmon_fprintf(void *, const char *, ...); | ||
20 | extern void xmon_sprintf(char *, const char *, ...); | ||
21 | 5 | ||
22 | #define perror(s) printf("%s: no files!\n", (s)) | 6 | extern int xmon_putchar(int c); |
7 | extern int xmon_getchar(void); | ||
8 | extern char *xmon_gets(char *, int); | ||
9 | extern void xmon_printf(const char *, ...); | ||
10 | extern void xmon_map_scc(void); | ||
11 | extern int xmon_expect(const char *str, unsigned long timeout); | ||
12 | extern int xmon_write(void *ptr, int nb); | ||
13 | extern int xmon_readchar(void); | ||
14 | extern int xmon_read_poll(void); | ||
diff --git a/arch/powerpc/xmon/setjmp.S b/arch/powerpc/xmon/setjmp.S index f8e40dfd2bff..96a91f10e2ec 100644 --- a/arch/powerpc/xmon/setjmp.S +++ b/arch/powerpc/xmon/setjmp.S | |||
@@ -14,61 +14,61 @@ | |||
14 | 14 | ||
15 | _GLOBAL(xmon_setjmp) | 15 | _GLOBAL(xmon_setjmp) |
16 | mflr r0 | 16 | mflr r0 |
17 | STL r0,0(r3) | 17 | PPC_STL r0,0(r3) |
18 | STL r1,SZL(r3) | 18 | PPC_STL r1,SZL(r3) |
19 | STL r2,2*SZL(r3) | 19 | PPC_STL r2,2*SZL(r3) |
20 | mfcr r0 | 20 | mfcr r0 |
21 | STL r0,3*SZL(r3) | 21 | PPC_STL r0,3*SZL(r3) |
22 | STL r13,4*SZL(r3) | 22 | PPC_STL r13,4*SZL(r3) |
23 | STL r14,5*SZL(r3) | 23 | PPC_STL r14,5*SZL(r3) |
24 | STL r15,6*SZL(r3) | 24 | PPC_STL r15,6*SZL(r3) |
25 | STL r16,7*SZL(r3) | 25 | PPC_STL r16,7*SZL(r3) |
26 | STL r17,8*SZL(r3) | 26 | PPC_STL r17,8*SZL(r3) |
27 | STL r18,9*SZL(r3) | 27 | PPC_STL r18,9*SZL(r3) |
28 | STL r19,10*SZL(r3) | 28 | PPC_STL r19,10*SZL(r3) |
29 | STL r20,11*SZL(r3) | 29 | PPC_STL r20,11*SZL(r3) |
30 | STL r21,12*SZL(r3) | 30 | PPC_STL r21,12*SZL(r3) |
31 | STL r22,13*SZL(r3) | 31 | PPC_STL r22,13*SZL(r3) |
32 | STL r23,14*SZL(r3) | 32 | PPC_STL r23,14*SZL(r3) |
33 | STL r24,15*SZL(r3) | 33 | PPC_STL r24,15*SZL(r3) |
34 | STL r25,16*SZL(r3) | 34 | PPC_STL r25,16*SZL(r3) |
35 | STL r26,17*SZL(r3) | 35 | PPC_STL r26,17*SZL(r3) |
36 | STL r27,18*SZL(r3) | 36 | PPC_STL r27,18*SZL(r3) |
37 | STL r28,19*SZL(r3) | 37 | PPC_STL r28,19*SZL(r3) |
38 | STL r29,20*SZL(r3) | 38 | PPC_STL r29,20*SZL(r3) |
39 | STL r30,21*SZL(r3) | 39 | PPC_STL r30,21*SZL(r3) |
40 | STL r31,22*SZL(r3) | 40 | PPC_STL r31,22*SZL(r3) |
41 | li r3,0 | 41 | li r3,0 |
42 | blr | 42 | blr |
43 | 43 | ||
44 | _GLOBAL(xmon_longjmp) | 44 | _GLOBAL(xmon_longjmp) |
45 | CMPI r4,0 | 45 | PPC_LCMPI r4,0 |
46 | bne 1f | 46 | bne 1f |
47 | li r4,1 | 47 | li r4,1 |
48 | 1: LDL r13,4*SZL(r3) | 48 | 1: PPC_LL r13,4*SZL(r3) |
49 | LDL r14,5*SZL(r3) | 49 | PPC_LL r14,5*SZL(r3) |
50 | LDL r15,6*SZL(r3) | 50 | PPC_LL r15,6*SZL(r3) |
51 | LDL r16,7*SZL(r3) | 51 | PPC_LL r16,7*SZL(r3) |
52 | LDL r17,8*SZL(r3) | 52 | PPC_LL r17,8*SZL(r3) |
53 | LDL r18,9*SZL(r3) | 53 | PPC_LL r18,9*SZL(r3) |
54 | LDL r19,10*SZL(r3) | 54 | PPC_LL r19,10*SZL(r3) |
55 | LDL r20,11*SZL(r3) | 55 | PPC_LL r20,11*SZL(r3) |
56 | LDL r21,12*SZL(r3) | 56 | PPC_LL r21,12*SZL(r3) |
57 | LDL r22,13*SZL(r3) | 57 | PPC_LL r22,13*SZL(r3) |
58 | LDL r23,14*SZL(r3) | 58 | PPC_LL r23,14*SZL(r3) |
59 | LDL r24,15*SZL(r3) | 59 | PPC_LL r24,15*SZL(r3) |
60 | LDL r25,16*SZL(r3) | 60 | PPC_LL r25,16*SZL(r3) |
61 | LDL r26,17*SZL(r3) | 61 | PPC_LL r26,17*SZL(r3) |
62 | LDL r27,18*SZL(r3) | 62 | PPC_LL r27,18*SZL(r3) |
63 | LDL r28,19*SZL(r3) | 63 | PPC_LL r28,19*SZL(r3) |
64 | LDL r29,20*SZL(r3) | 64 | PPC_LL r29,20*SZL(r3) |
65 | LDL r30,21*SZL(r3) | 65 | PPC_LL r30,21*SZL(r3) |
66 | LDL r31,22*SZL(r3) | 66 | PPC_LL r31,22*SZL(r3) |
67 | LDL r0,3*SZL(r3) | 67 | PPC_LL r0,3*SZL(r3) |
68 | mtcrf 0x38,r0 | 68 | mtcrf 0x38,r0 |
69 | LDL r0,0(r3) | 69 | PPC_LL r0,0(r3) |
70 | LDL r1,SZL(r3) | 70 | PPC_LL r1,SZL(r3) |
71 | LDL r2,2*SZL(r3) | 71 | PPC_LL r2,2*SZL(r3) |
72 | mtlr r0 | 72 | mtlr r0 |
73 | mr r3,r4 | 73 | mr r3,r4 |
74 | blr | 74 | blr |
@@ -84,52 +84,52 @@ _GLOBAL(xmon_longjmp) | |||
84 | * different ABIs, though). | 84 | * different ABIs, though). |
85 | */ | 85 | */ |
86 | _GLOBAL(xmon_save_regs) | 86 | _GLOBAL(xmon_save_regs) |
87 | STL r0,0*SZL(r3) | 87 | PPC_STL r0,0*SZL(r3) |
88 | STL r2,2*SZL(r3) | 88 | PPC_STL r2,2*SZL(r3) |
89 | STL r3,3*SZL(r3) | 89 | PPC_STL r3,3*SZL(r3) |
90 | STL r4,4*SZL(r3) | 90 | PPC_STL r4,4*SZL(r3) |
91 | STL r5,5*SZL(r3) | 91 | PPC_STL r5,5*SZL(r3) |
92 | STL r6,6*SZL(r3) | 92 | PPC_STL r6,6*SZL(r3) |
93 | STL r7,7*SZL(r3) | 93 | PPC_STL r7,7*SZL(r3) |
94 | STL r8,8*SZL(r3) | 94 | PPC_STL r8,8*SZL(r3) |
95 | STL r9,9*SZL(r3) | 95 | PPC_STL r9,9*SZL(r3) |
96 | STL r10,10*SZL(r3) | 96 | PPC_STL r10,10*SZL(r3) |
97 | STL r11,11*SZL(r3) | 97 | PPC_STL r11,11*SZL(r3) |
98 | STL r12,12*SZL(r3) | 98 | PPC_STL r12,12*SZL(r3) |
99 | STL r13,13*SZL(r3) | 99 | PPC_STL r13,13*SZL(r3) |
100 | STL r14,14*SZL(r3) | 100 | PPC_STL r14,14*SZL(r3) |
101 | STL r15,15*SZL(r3) | 101 | PPC_STL r15,15*SZL(r3) |
102 | STL r16,16*SZL(r3) | 102 | PPC_STL r16,16*SZL(r3) |
103 | STL r17,17*SZL(r3) | 103 | PPC_STL r17,17*SZL(r3) |
104 | STL r18,18*SZL(r3) | 104 | PPC_STL r18,18*SZL(r3) |
105 | STL r19,19*SZL(r3) | 105 | PPC_STL r19,19*SZL(r3) |
106 | STL r20,20*SZL(r3) | 106 | PPC_STL r20,20*SZL(r3) |
107 | STL r21,21*SZL(r3) | 107 | PPC_STL r21,21*SZL(r3) |
108 | STL r22,22*SZL(r3) | 108 | PPC_STL r22,22*SZL(r3) |
109 | STL r23,23*SZL(r3) | 109 | PPC_STL r23,23*SZL(r3) |
110 | STL r24,24*SZL(r3) | 110 | PPC_STL r24,24*SZL(r3) |
111 | STL r25,25*SZL(r3) | 111 | PPC_STL r25,25*SZL(r3) |
112 | STL r26,26*SZL(r3) | 112 | PPC_STL r26,26*SZL(r3) |
113 | STL r27,27*SZL(r3) | 113 | PPC_STL r27,27*SZL(r3) |
114 | STL r28,28*SZL(r3) | 114 | PPC_STL r28,28*SZL(r3) |
115 | STL r29,29*SZL(r3) | 115 | PPC_STL r29,29*SZL(r3) |
116 | STL r30,30*SZL(r3) | 116 | PPC_STL r30,30*SZL(r3) |
117 | STL r31,31*SZL(r3) | 117 | PPC_STL r31,31*SZL(r3) |
118 | /* go up one stack frame for SP */ | 118 | /* go up one stack frame for SP */ |
119 | LDL r4,0(r1) | 119 | PPC_LL r4,0(r1) |
120 | STL r4,1*SZL(r3) | 120 | PPC_STL r4,1*SZL(r3) |
121 | /* get caller's LR */ | 121 | /* get caller's LR */ |
122 | LDL r0,LRSAVE(r4) | 122 | PPC_LL r0,LRSAVE(r4) |
123 | STL r0,_NIP-STACK_FRAME_OVERHEAD(r3) | 123 | PPC_STL r0,_NIP-STACK_FRAME_OVERHEAD(r3) |
124 | STL r0,_LINK-STACK_FRAME_OVERHEAD(r3) | 124 | PPC_STL r0,_LINK-STACK_FRAME_OVERHEAD(r3) |
125 | mfmsr r0 | 125 | mfmsr r0 |
126 | STL r0,_MSR-STACK_FRAME_OVERHEAD(r3) | 126 | PPC_STL r0,_MSR-STACK_FRAME_OVERHEAD(r3) |
127 | mfctr r0 | 127 | mfctr r0 |
128 | STL r0,_CTR-STACK_FRAME_OVERHEAD(r3) | 128 | PPC_STL r0,_CTR-STACK_FRAME_OVERHEAD(r3) |
129 | mfxer r0 | 129 | mfxer r0 |
130 | STL r0,_XER-STACK_FRAME_OVERHEAD(r3) | 130 | PPC_STL r0,_XER-STACK_FRAME_OVERHEAD(r3) |
131 | mfcr r0 | 131 | mfcr r0 |
132 | STL r0,_CCR-STACK_FRAME_OVERHEAD(r3) | 132 | PPC_STL r0,_CCR-STACK_FRAME_OVERHEAD(r3) |
133 | li r0,0 | 133 | li r0,0 |
134 | STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3) | 134 | PPC_STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3) |
135 | blr | 135 | blr |
diff --git a/arch/powerpc/xmon/start_32.c b/arch/powerpc/xmon/start_32.c index 69b658c0f760..c2464df4217e 100644 --- a/arch/powerpc/xmon/start_32.c +++ b/arch/powerpc/xmon/start_32.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/cuda.h> | 11 | #include <linux/cuda.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/sysrq.h> | ||
15 | #include <linux/bitops.h> | 14 | #include <linux/bitops.h> |
16 | #include <asm/xmon.h> | 15 | #include <asm/xmon.h> |
17 | #include <asm/prom.h> | 16 | #include <asm/prom.h> |
@@ -22,10 +21,11 @@ | |||
22 | #include <asm/processor.h> | 21 | #include <asm/processor.h> |
23 | #include <asm/delay.h> | 22 | #include <asm/delay.h> |
24 | #include <asm/btext.h> | 23 | #include <asm/btext.h> |
24 | #include <asm/time.h> | ||
25 | #include "nonstdio.h" | ||
25 | 26 | ||
26 | static volatile unsigned char __iomem *sccc, *sccd; | 27 | static volatile unsigned char __iomem *sccc, *sccd; |
27 | unsigned int TXRDY, RXRDY, DLAB; | 28 | unsigned int TXRDY, RXRDY, DLAB; |
28 | static int xmon_expect(const char *str, unsigned int timeout); | ||
29 | 29 | ||
30 | static int use_serial; | 30 | static int use_serial; |
31 | static int use_screen; | 31 | static int use_screen; |
@@ -33,16 +33,6 @@ static int via_modem; | |||
33 | static int xmon_use_sccb; | 33 | static int xmon_use_sccb; |
34 | static struct device_node *channel_node; | 34 | static struct device_node *channel_node; |
35 | 35 | ||
36 | #define TB_SPEED 25000000 | ||
37 | |||
38 | static inline unsigned int readtb(void) | ||
39 | { | ||
40 | unsigned int ret; | ||
41 | |||
42 | asm volatile("mftb %0" : "=r" (ret) :); | ||
43 | return ret; | ||
44 | } | ||
45 | |||
46 | void buf_access(void) | 36 | void buf_access(void) |
47 | { | 37 | { |
48 | if (DLAB) | 38 | if (DLAB) |
@@ -91,23 +81,7 @@ static unsigned long chrp_find_phys_io_base(void) | |||
91 | } | 81 | } |
92 | #endif /* CONFIG_PPC_CHRP */ | 82 | #endif /* CONFIG_PPC_CHRP */ |
93 | 83 | ||
94 | #ifdef CONFIG_MAGIC_SYSRQ | 84 | void xmon_map_scc(void) |
95 | static void sysrq_handle_xmon(int key, struct pt_regs *regs, | ||
96 | struct tty_struct *tty) | ||
97 | { | ||
98 | xmon(regs); | ||
99 | } | ||
100 | |||
101 | static struct sysrq_key_op sysrq_xmon_op = | ||
102 | { | ||
103 | .handler = sysrq_handle_xmon, | ||
104 | .help_msg = "Xmon", | ||
105 | .action_msg = "Entering xmon", | ||
106 | }; | ||
107 | #endif | ||
108 | |||
109 | void | ||
110 | xmon_map_scc(void) | ||
111 | { | 85 | { |
112 | #ifdef CONFIG_PPC_MULTIPLATFORM | 86 | #ifdef CONFIG_PPC_MULTIPLATFORM |
113 | volatile unsigned char __iomem *base; | 87 | volatile unsigned char __iomem *base; |
@@ -217,8 +191,6 @@ xmon_map_scc(void) | |||
217 | RXRDY = 1; | 191 | RXRDY = 1; |
218 | DLAB = 0x80; | 192 | DLAB = 0x80; |
219 | #endif /* platform */ | 193 | #endif /* platform */ |
220 | |||
221 | register_sysrq_key('x', &sysrq_xmon_op); | ||
222 | } | 194 | } |
223 | 195 | ||
224 | static int scc_initialized = 0; | 196 | static int scc_initialized = 0; |
@@ -238,8 +210,7 @@ static inline void do_poll_adb(void) | |||
238 | #endif /* CONFIG_ADB_CUDA */ | 210 | #endif /* CONFIG_ADB_CUDA */ |
239 | } | 211 | } |
240 | 212 | ||
241 | int | 213 | int xmon_write(void *ptr, int nb) |
242 | xmon_write(void *handle, void *ptr, int nb) | ||
243 | { | 214 | { |
244 | char *p = ptr; | 215 | char *p = ptr; |
245 | int i, c, ct; | 216 | int i, c, ct; |
@@ -311,8 +282,7 @@ static unsigned char xmon_shift_keytab[128] = | |||
311 | "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */ | 282 | "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */ |
312 | "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */ | 283 | "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */ |
313 | 284 | ||
314 | static int | 285 | static int xmon_get_adb_key(void) |
315 | xmon_get_adb_key(void) | ||
316 | { | 286 | { |
317 | int k, t, on; | 287 | int k, t, on; |
318 | 288 | ||
@@ -350,32 +320,21 @@ xmon_get_adb_key(void) | |||
350 | } | 320 | } |
351 | #endif /* CONFIG_BOOTX_TEXT */ | 321 | #endif /* CONFIG_BOOTX_TEXT */ |
352 | 322 | ||
353 | int | 323 | int xmon_readchar(void) |
354 | xmon_read(void *handle, void *ptr, int nb) | ||
355 | { | 324 | { |
356 | char *p = ptr; | ||
357 | int i; | ||
358 | |||
359 | #ifdef CONFIG_BOOTX_TEXT | 325 | #ifdef CONFIG_BOOTX_TEXT |
360 | if (use_screen) { | 326 | if (use_screen) |
361 | for (i = 0; i < nb; ++i) | 327 | return xmon_get_adb_key(); |
362 | *p++ = xmon_get_adb_key(); | ||
363 | return i; | ||
364 | } | ||
365 | #endif | 328 | #endif |
366 | if (!scc_initialized) | 329 | if (!scc_initialized) |
367 | xmon_init_scc(); | 330 | xmon_init_scc(); |
368 | for (i = 0; i < nb; ++i) { | ||
369 | while ((*sccc & RXRDY) == 0) | 331 | while ((*sccc & RXRDY) == 0) |
370 | do_poll_adb(); | 332 | do_poll_adb(); |
371 | buf_access(); | 333 | buf_access(); |
372 | *p++ = *sccd; | 334 | return *sccd; |
373 | } | ||
374 | return i; | ||
375 | } | 335 | } |
376 | 336 | ||
377 | int | 337 | int xmon_read_poll(void) |
378 | xmon_read_poll(void) | ||
379 | { | 338 | { |
380 | if ((*sccc & RXRDY) == 0) { | 339 | if ((*sccc & RXRDY) == 0) { |
381 | do_poll_adb(); | 340 | do_poll_adb(); |
@@ -395,8 +354,7 @@ static unsigned char scc_inittab[] = { | |||
395 | 3, 0xc1, /* rx enable, 8 bits */ | 354 | 3, 0xc1, /* rx enable, 8 bits */ |
396 | }; | 355 | }; |
397 | 356 | ||
398 | void | 357 | void xmon_init_scc(void) |
399 | xmon_init_scc(void) | ||
400 | { | 358 | { |
401 | if ( _machine == _MACH_chrp ) | 359 | if ( _machine == _MACH_chrp ) |
402 | { | 360 | { |
@@ -410,6 +368,7 @@ xmon_init_scc(void) | |||
410 | else if ( _machine == _MACH_Pmac ) | 368 | else if ( _machine == _MACH_Pmac ) |
411 | { | 369 | { |
412 | int i, x; | 370 | int i, x; |
371 | unsigned long timeout; | ||
413 | 372 | ||
414 | if (channel_node != 0) | 373 | if (channel_node != 0) |
415 | pmac_call_feature( | 374 | pmac_call_feature( |
@@ -424,8 +383,12 @@ xmon_init_scc(void) | |||
424 | PMAC_FTR_MODEM_ENABLE, | 383 | PMAC_FTR_MODEM_ENABLE, |
425 | channel_node, 0, 1); | 384 | channel_node, 0, 1); |
426 | printk(KERN_INFO "Modem powered up by debugger !\n"); | 385 | printk(KERN_INFO "Modem powered up by debugger !\n"); |
427 | t0 = readtb(); | 386 | t0 = get_tbl(); |
428 | while (readtb() - t0 < 3*TB_SPEED) | 387 | timeout = 3 * tb_ticks_per_sec; |
388 | if (timeout == 0) | ||
389 | /* assume 25MHz if tb_ticks_per_sec not set */ | ||
390 | timeout = 75000000; | ||
391 | while (get_tbl() - t0 < timeout) | ||
429 | eieio(); | 392 | eieio(); |
430 | } | 393 | } |
431 | /* use the B channel if requested */ | 394 | /* use the B channel if requested */ |
@@ -447,164 +410,19 @@ xmon_init_scc(void) | |||
447 | scc_initialized = 1; | 410 | scc_initialized = 1; |
448 | if (via_modem) { | 411 | if (via_modem) { |
449 | for (;;) { | 412 | for (;;) { |
450 | xmon_write(NULL, "ATE1V1\r", 7); | 413 | xmon_write("ATE1V1\r", 7); |
451 | if (xmon_expect("OK", 5)) { | 414 | if (xmon_expect("OK", 5)) { |
452 | xmon_write(NULL, "ATA\r", 4); | 415 | xmon_write("ATA\r", 4); |
453 | if (xmon_expect("CONNECT", 40)) | 416 | if (xmon_expect("CONNECT", 40)) |
454 | break; | 417 | break; |
455 | } | 418 | } |
456 | xmon_write(NULL, "+++", 3); | 419 | xmon_write("+++", 3); |
457 | xmon_expect("OK", 3); | 420 | xmon_expect("OK", 3); |
458 | } | 421 | } |
459 | } | 422 | } |
460 | } | 423 | } |
461 | 424 | ||
462 | void *xmon_stdin; | 425 | void xmon_enter(void) |
463 | void *xmon_stdout; | ||
464 | void *xmon_stderr; | ||
465 | |||
466 | int xmon_putc(int c, void *f) | ||
467 | { | ||
468 | char ch = c; | ||
469 | |||
470 | if (c == '\n') | ||
471 | xmon_putc('\r', f); | ||
472 | return xmon_write(f, &ch, 1) == 1? c: -1; | ||
473 | } | ||
474 | |||
475 | int xmon_putchar(int c) | ||
476 | { | ||
477 | return xmon_putc(c, xmon_stdout); | ||
478 | } | ||
479 | |||
480 | int xmon_fputs(char *str, void *f) | ||
481 | { | ||
482 | int n = strlen(str); | ||
483 | |||
484 | return xmon_write(f, str, n) == n? 0: -1; | ||
485 | } | ||
486 | |||
487 | int | ||
488 | xmon_readchar(void) | ||
489 | { | ||
490 | char ch; | ||
491 | |||
492 | for (;;) { | ||
493 | switch (xmon_read(xmon_stdin, &ch, 1)) { | ||
494 | case 1: | ||
495 | return ch; | ||
496 | case -1: | ||
497 | xmon_printf("read(stdin) returned -1\r\n", 0, 0); | ||
498 | return -1; | ||
499 | } | ||
500 | } | ||
501 | } | ||
502 | |||
503 | static char line[256]; | ||
504 | static char *lineptr; | ||
505 | static int lineleft; | ||
506 | |||
507 | int xmon_expect(const char *str, unsigned int timeout) | ||
508 | { | ||
509 | int c; | ||
510 | unsigned int t0; | ||
511 | |||
512 | timeout *= TB_SPEED; | ||
513 | t0 = readtb(); | ||
514 | do { | ||
515 | lineptr = line; | ||
516 | for (;;) { | ||
517 | c = xmon_read_poll(); | ||
518 | if (c == -1) { | ||
519 | if (readtb() - t0 > timeout) | ||
520 | return 0; | ||
521 | continue; | ||
522 | } | ||
523 | if (c == '\n') | ||
524 | break; | ||
525 | if (c != '\r' && lineptr < &line[sizeof(line) - 1]) | ||
526 | *lineptr++ = c; | ||
527 | } | ||
528 | *lineptr = 0; | ||
529 | } while (strstr(line, str) == NULL); | ||
530 | return 1; | ||
531 | } | ||
532 | |||
533 | int | ||
534 | xmon_getchar(void) | ||
535 | { | ||
536 | int c; | ||
537 | |||
538 | if (lineleft == 0) { | ||
539 | lineptr = line; | ||
540 | for (;;) { | ||
541 | c = xmon_readchar(); | ||
542 | if (c == -1 || c == 4) | ||
543 | break; | ||
544 | if (c == '\r' || c == '\n') { | ||
545 | *lineptr++ = '\n'; | ||
546 | xmon_putchar('\n'); | ||
547 | break; | ||
548 | } | ||
549 | switch (c) { | ||
550 | case 0177: | ||
551 | case '\b': | ||
552 | if (lineptr > line) { | ||
553 | xmon_putchar('\b'); | ||
554 | xmon_putchar(' '); | ||
555 | xmon_putchar('\b'); | ||
556 | --lineptr; | ||
557 | } | ||
558 | break; | ||
559 | case 'U' & 0x1F: | ||
560 | while (lineptr > line) { | ||
561 | xmon_putchar('\b'); | ||
562 | xmon_putchar(' '); | ||
563 | xmon_putchar('\b'); | ||
564 | --lineptr; | ||
565 | } | ||
566 | break; | ||
567 | default: | ||
568 | if (lineptr >= &line[sizeof(line) - 1]) | ||
569 | xmon_putchar('\a'); | ||
570 | else { | ||
571 | xmon_putchar(c); | ||
572 | *lineptr++ = c; | ||
573 | } | ||
574 | } | ||
575 | } | ||
576 | lineleft = lineptr - line; | ||
577 | lineptr = line; | ||
578 | } | ||
579 | if (lineleft == 0) | ||
580 | return -1; | ||
581 | --lineleft; | ||
582 | return *lineptr++; | ||
583 | } | ||
584 | |||
585 | char * | ||
586 | xmon_fgets(char *str, int nb, void *f) | ||
587 | { | ||
588 | char *p; | ||
589 | int c; | ||
590 | |||
591 | for (p = str; p < str + nb - 1; ) { | ||
592 | c = xmon_getchar(); | ||
593 | if (c == -1) { | ||
594 | if (p == str) | ||
595 | return NULL; | ||
596 | break; | ||
597 | } | ||
598 | *p++ = c; | ||
599 | if (c == '\n') | ||
600 | break; | ||
601 | } | ||
602 | *p = 0; | ||
603 | return str; | ||
604 | } | ||
605 | |||
606 | void | ||
607 | xmon_enter(void) | ||
608 | { | 426 | { |
609 | #ifdef CONFIG_ADB_PMU | 427 | #ifdef CONFIG_ADB_PMU |
610 | if (_machine == _MACH_Pmac) { | 428 | if (_machine == _MACH_Pmac) { |
@@ -613,8 +431,7 @@ xmon_enter(void) | |||
613 | #endif | 431 | #endif |
614 | } | 432 | } |
615 | 433 | ||
616 | void | 434 | void xmon_leave(void) |
617 | xmon_leave(void) | ||
618 | { | 435 | { |
619 | #ifdef CONFIG_ADB_PMU | 436 | #ifdef CONFIG_ADB_PMU |
620 | if (_machine == _MACH_Pmac) { | 437 | if (_machine == _MACH_Pmac) { |
diff --git a/arch/powerpc/xmon/start_64.c b/arch/powerpc/xmon/start_64.c index e50c158191e1..712552c4f242 100644 --- a/arch/powerpc/xmon/start_64.c +++ b/arch/powerpc/xmon/start_64.c | |||
@@ -6,182 +6,29 @@ | |||
6 | * as published by the Free Software Foundation; either version | 6 | * as published by the Free Software Foundation; either version |
7 | * 2 of the License, or (at your option) any later version. | 7 | * 2 of the License, or (at your option) any later version. |
8 | */ | 8 | */ |
9 | #include <linux/config.h> | ||
10 | #include <linux/string.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/sysrq.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <asm/machdep.h> | 9 | #include <asm/machdep.h> |
16 | #include <asm/io.h> | ||
17 | #include <asm/page.h> | ||
18 | #include <asm/prom.h> | ||
19 | #include <asm/processor.h> | ||
20 | #include <asm/udbg.h> | 10 | #include <asm/udbg.h> |
21 | #include <asm/system.h> | ||
22 | #include "nonstdio.h" | 11 | #include "nonstdio.h" |
23 | 12 | ||
24 | #ifdef CONFIG_MAGIC_SYSRQ | 13 | void xmon_map_scc(void) |
25 | |||
26 | static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs, | ||
27 | struct tty_struct *tty) | ||
28 | { | ||
29 | /* ensure xmon is enabled */ | ||
30 | xmon_init(1); | ||
31 | debugger(pt_regs); | ||
32 | } | ||
33 | |||
34 | static struct sysrq_key_op sysrq_xmon_op = | ||
35 | { | 14 | { |
36 | .handler = sysrq_handle_xmon, | ||
37 | .help_msg = "Xmon", | ||
38 | .action_msg = "Entering xmon", | ||
39 | }; | ||
40 | |||
41 | static int __init setup_xmon_sysrq(void) | ||
42 | { | ||
43 | register_sysrq_key('x', &sysrq_xmon_op); | ||
44 | return 0; | ||
45 | } | 15 | } |
46 | __initcall(setup_xmon_sysrq); | ||
47 | #endif /* CONFIG_MAGIC_SYSRQ */ | ||
48 | 16 | ||
49 | int | 17 | int xmon_write(void *ptr, int nb) |
50 | xmon_write(void *handle, void *ptr, int nb) | ||
51 | { | 18 | { |
52 | return udbg_write(ptr, nb); | 19 | return udbg_write(ptr, nb); |
53 | } | 20 | } |
54 | 21 | ||
55 | int | 22 | int xmon_readchar(void) |
56 | xmon_read(void *handle, void *ptr, int nb) | ||
57 | { | 23 | { |
58 | return udbg_read(ptr, nb); | 24 | if (udbg_getc) |
25 | return udbg_getc(); | ||
26 | return -1; | ||
59 | } | 27 | } |
60 | 28 | ||
61 | int | 29 | int xmon_read_poll(void) |
62 | xmon_read_poll(void) | ||
63 | { | 30 | { |
64 | if (udbg_getc_poll) | 31 | if (udbg_getc_poll) |
65 | return udbg_getc_poll(); | 32 | return udbg_getc_poll(); |
66 | return -1; | 33 | return -1; |
67 | } | 34 | } |
68 | |||
69 | FILE *xmon_stdin; | ||
70 | FILE *xmon_stdout; | ||
71 | |||
72 | int | ||
73 | xmon_putc(int c, void *f) | ||
74 | { | ||
75 | char ch = c; | ||
76 | |||
77 | if (c == '\n') | ||
78 | xmon_putc('\r', f); | ||
79 | return xmon_write(f, &ch, 1) == 1? c: -1; | ||
80 | } | ||
81 | |||
82 | int | ||
83 | xmon_putchar(int c) | ||
84 | { | ||
85 | return xmon_putc(c, xmon_stdout); | ||
86 | } | ||
87 | |||
88 | int | ||
89 | xmon_fputs(char *str, void *f) | ||
90 | { | ||
91 | int n = strlen(str); | ||
92 | |||
93 | return xmon_write(f, str, n) == n? 0: -1; | ||
94 | } | ||
95 | |||
96 | int | ||
97 | xmon_readchar(void) | ||
98 | { | ||
99 | char ch; | ||
100 | |||
101 | for (;;) { | ||
102 | switch (xmon_read(xmon_stdin, &ch, 1)) { | ||
103 | case 1: | ||
104 | return ch; | ||
105 | case -1: | ||
106 | xmon_printf("read(stdin) returned -1\r\n", 0, 0); | ||
107 | return -1; | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | |||
112 | static char line[256]; | ||
113 | static char *lineptr; | ||
114 | static int lineleft; | ||
115 | |||
116 | int | ||
117 | xmon_getchar(void) | ||
118 | { | ||
119 | int c; | ||
120 | |||
121 | if (lineleft == 0) { | ||
122 | lineptr = line; | ||
123 | for (;;) { | ||
124 | c = xmon_readchar(); | ||
125 | if (c == -1 || c == 4) | ||
126 | break; | ||
127 | if (c == '\r' || c == '\n') { | ||
128 | *lineptr++ = '\n'; | ||
129 | xmon_putchar('\n'); | ||
130 | break; | ||
131 | } | ||
132 | switch (c) { | ||
133 | case 0177: | ||
134 | case '\b': | ||
135 | if (lineptr > line) { | ||
136 | xmon_putchar('\b'); | ||
137 | xmon_putchar(' '); | ||
138 | xmon_putchar('\b'); | ||
139 | --lineptr; | ||
140 | } | ||
141 | break; | ||
142 | case 'U' & 0x1F: | ||
143 | while (lineptr > line) { | ||
144 | xmon_putchar('\b'); | ||
145 | xmon_putchar(' '); | ||
146 | xmon_putchar('\b'); | ||
147 | --lineptr; | ||
148 | } | ||
149 | break; | ||
150 | default: | ||
151 | if (lineptr >= &line[sizeof(line) - 1]) | ||
152 | xmon_putchar('\a'); | ||
153 | else { | ||
154 | xmon_putchar(c); | ||
155 | *lineptr++ = c; | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | lineleft = lineptr - line; | ||
160 | lineptr = line; | ||
161 | } | ||
162 | if (lineleft == 0) | ||
163 | return -1; | ||
164 | --lineleft; | ||
165 | return *lineptr++; | ||
166 | } | ||
167 | |||
168 | char * | ||
169 | xmon_fgets(char *str, int nb, void *f) | ||
170 | { | ||
171 | char *p; | ||
172 | int c; | ||
173 | |||
174 | for (p = str; p < str + nb - 1; ) { | ||
175 | c = xmon_getchar(); | ||
176 | if (c == -1) { | ||
177 | if (p == str) | ||
178 | return NULL; | ||
179 | break; | ||
180 | } | ||
181 | *p++ = c; | ||
182 | if (c == '\n') | ||
183 | break; | ||
184 | } | ||
185 | *p = 0; | ||
186 | return str; | ||
187 | } | ||
diff --git a/arch/powerpc/xmon/start_8xx.c b/arch/powerpc/xmon/start_8xx.c index a48bd594cf61..4c17b0486ad5 100644 --- a/arch/powerpc/xmon/start_8xx.c +++ b/arch/powerpc/xmon/start_8xx.c | |||
@@ -15,273 +15,30 @@ | |||
15 | #include <asm/8xx_immap.h> | 15 | #include <asm/8xx_immap.h> |
16 | #include <asm/mpc8xx.h> | 16 | #include <asm/mpc8xx.h> |
17 | #include <asm/commproc.h> | 17 | #include <asm/commproc.h> |
18 | #include "nonstdio.h" | ||
18 | 19 | ||
19 | extern void xmon_printf(const char *fmt, ...); | ||
20 | extern int xmon_8xx_write(char *str, int nb); | 20 | extern int xmon_8xx_write(char *str, int nb); |
21 | extern int xmon_8xx_read_poll(void); | 21 | extern int xmon_8xx_read_poll(void); |
22 | extern int xmon_8xx_read_char(void); | 22 | extern int xmon_8xx_read_char(void); |
23 | void prom_drawhex(uint); | ||
24 | void prom_drawstring(const char *str); | ||
25 | 23 | ||
26 | static int use_screen = 1; /* default */ | 24 | void xmon_map_scc(void) |
27 | |||
28 | #define TB_SPEED 25000000 | ||
29 | |||
30 | static inline unsigned int readtb(void) | ||
31 | { | ||
32 | unsigned int ret; | ||
33 | |||
34 | asm volatile("mftb %0" : "=r" (ret) :); | ||
35 | return ret; | ||
36 | } | ||
37 | |||
38 | void buf_access(void) | ||
39 | { | ||
40 | } | ||
41 | |||
42 | void | ||
43 | xmon_map_scc(void) | ||
44 | { | 25 | { |
45 | |||
46 | cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm); | 26 | cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm); |
47 | use_screen = 0; | ||
48 | |||
49 | prom_drawstring("xmon uses serial port\n"); | ||
50 | } | 27 | } |
51 | 28 | ||
52 | static int scc_initialized = 0; | ||
53 | |||
54 | void xmon_init_scc(void); | 29 | void xmon_init_scc(void); |
55 | 30 | ||
56 | int | 31 | int xmon_write(void *ptr, int nb) |
57 | xmon_write(void *handle, void *ptr, int nb) | ||
58 | { | 32 | { |
59 | char *p = ptr; | ||
60 | int i, c, ct; | ||
61 | |||
62 | if (!scc_initialized) | ||
63 | xmon_init_scc(); | ||
64 | |||
65 | return(xmon_8xx_write(ptr, nb)); | 33 | return(xmon_8xx_write(ptr, nb)); |
66 | } | 34 | } |
67 | 35 | ||
68 | int xmon_wants_key; | 36 | int xmon_readchar(void) |
69 | |||
70 | int | ||
71 | xmon_read(void *handle, void *ptr, int nb) | ||
72 | { | 37 | { |
73 | char *p = ptr; | 38 | return xmon_8xx_read_char(); |
74 | int i; | ||
75 | |||
76 | if (!scc_initialized) | ||
77 | xmon_init_scc(); | ||
78 | |||
79 | for (i = 0; i < nb; ++i) { | ||
80 | *p++ = xmon_8xx_read_char(); | ||
81 | } | ||
82 | return i; | ||
83 | } | 39 | } |
84 | 40 | ||
85 | int | 41 | int xmon_read_poll(void) |
86 | xmon_read_poll(void) | ||
87 | { | 42 | { |
88 | return(xmon_8xx_read_poll()); | 43 | return(xmon_8xx_read_poll()); |
89 | } | 44 | } |
90 | |||
91 | void | ||
92 | xmon_init_scc() | ||
93 | { | ||
94 | scc_initialized = 1; | ||
95 | } | ||
96 | |||
97 | #if 0 | ||
98 | extern int (*prom_entry)(void *); | ||
99 | |||
100 | int | ||
101 | xmon_exit(void) | ||
102 | { | ||
103 | struct prom_args { | ||
104 | char *service; | ||
105 | } args; | ||
106 | |||
107 | for (;;) { | ||
108 | args.service = "exit"; | ||
109 | (*prom_entry)(&args); | ||
110 | } | ||
111 | } | ||
112 | #endif | ||
113 | |||
114 | void *xmon_stdin; | ||
115 | void *xmon_stdout; | ||
116 | void *xmon_stderr; | ||
117 | |||
118 | void | ||
119 | xmon_init(void) | ||
120 | { | ||
121 | } | ||
122 | |||
123 | int | ||
124 | xmon_putc(int c, void *f) | ||
125 | { | ||
126 | char ch = c; | ||
127 | |||
128 | if (c == '\n') | ||
129 | xmon_putc('\r', f); | ||
130 | return xmon_write(f, &ch, 1) == 1? c: -1; | ||
131 | } | ||
132 | |||
133 | int | ||
134 | xmon_putchar(int c) | ||
135 | { | ||
136 | return xmon_putc(c, xmon_stdout); | ||
137 | } | ||
138 | |||
139 | int | ||
140 | xmon_fputs(char *str, void *f) | ||
141 | { | ||
142 | int n = strlen(str); | ||
143 | |||
144 | return xmon_write(f, str, n) == n? 0: -1; | ||
145 | } | ||
146 | |||
147 | int | ||
148 | xmon_readchar(void) | ||
149 | { | ||
150 | char ch; | ||
151 | |||
152 | for (;;) { | ||
153 | switch (xmon_read(xmon_stdin, &ch, 1)) { | ||
154 | case 1: | ||
155 | return ch; | ||
156 | case -1: | ||
157 | xmon_printf("read(stdin) returned -1\r\n", 0, 0); | ||
158 | return -1; | ||
159 | } | ||
160 | } | ||
161 | } | ||
162 | |||
163 | static char line[256]; | ||
164 | static char *lineptr; | ||
165 | static int lineleft; | ||
166 | |||
167 | #if 0 | ||
168 | int xmon_expect(const char *str, unsigned int timeout) | ||
169 | { | ||
170 | int c; | ||
171 | unsigned int t0; | ||
172 | |||
173 | timeout *= TB_SPEED; | ||
174 | t0 = readtb(); | ||
175 | do { | ||
176 | lineptr = line; | ||
177 | for (;;) { | ||
178 | c = xmon_read_poll(); | ||
179 | if (c == -1) { | ||
180 | if (readtb() - t0 > timeout) | ||
181 | return 0; | ||
182 | continue; | ||
183 | } | ||
184 | if (c == '\n') | ||
185 | break; | ||
186 | if (c != '\r' && lineptr < &line[sizeof(line) - 1]) | ||
187 | *lineptr++ = c; | ||
188 | } | ||
189 | *lineptr = 0; | ||
190 | } while (strstr(line, str) == NULL); | ||
191 | return 1; | ||
192 | } | ||
193 | #endif | ||
194 | |||
195 | int | ||
196 | xmon_getchar(void) | ||
197 | { | ||
198 | int c; | ||
199 | |||
200 | if (lineleft == 0) { | ||
201 | lineptr = line; | ||
202 | for (;;) { | ||
203 | c = xmon_readchar(); | ||
204 | if (c == -1 || c == 4) | ||
205 | break; | ||
206 | if (c == '\r' || c == '\n') { | ||
207 | *lineptr++ = '\n'; | ||
208 | xmon_putchar('\n'); | ||
209 | break; | ||
210 | } | ||
211 | switch (c) { | ||
212 | case 0177: | ||
213 | case '\b': | ||
214 | if (lineptr > line) { | ||
215 | xmon_putchar('\b'); | ||
216 | xmon_putchar(' '); | ||
217 | xmon_putchar('\b'); | ||
218 | --lineptr; | ||
219 | } | ||
220 | break; | ||
221 | case 'U' & 0x1F: | ||
222 | while (lineptr > line) { | ||
223 | xmon_putchar('\b'); | ||
224 | xmon_putchar(' '); | ||
225 | xmon_putchar('\b'); | ||
226 | --lineptr; | ||
227 | } | ||
228 | break; | ||
229 | default: | ||
230 | if (lineptr >= &line[sizeof(line) - 1]) | ||
231 | xmon_putchar('\a'); | ||
232 | else { | ||
233 | xmon_putchar(c); | ||
234 | *lineptr++ = c; | ||
235 | } | ||
236 | } | ||
237 | } | ||
238 | lineleft = lineptr - line; | ||
239 | lineptr = line; | ||
240 | } | ||
241 | if (lineleft == 0) | ||
242 | return -1; | ||
243 | --lineleft; | ||
244 | return *lineptr++; | ||
245 | } | ||
246 | |||
247 | char * | ||
248 | xmon_fgets(char *str, int nb, void *f) | ||
249 | { | ||
250 | char *p; | ||
251 | int c; | ||
252 | |||
253 | for (p = str; p < str + nb - 1; ) { | ||
254 | c = xmon_getchar(); | ||
255 | if (c == -1) { | ||
256 | if (p == str) | ||
257 | return 0; | ||
258 | break; | ||
259 | } | ||
260 | *p++ = c; | ||
261 | if (c == '\n') | ||
262 | break; | ||
263 | } | ||
264 | *p = 0; | ||
265 | return str; | ||
266 | } | ||
267 | |||
268 | void | ||
269 | prom_drawhex(uint val) | ||
270 | { | ||
271 | unsigned char buf[10]; | ||
272 | |||
273 | int i; | ||
274 | for (i = 7; i >= 0; i--) | ||
275 | { | ||
276 | buf[i] = "0123456789abcdef"[val & 0x0f]; | ||
277 | val >>= 4; | ||
278 | } | ||
279 | buf[8] = '\0'; | ||
280 | xmon_fputs(buf, xmon_stdout); | ||
281 | } | ||
282 | |||
283 | void | ||
284 | prom_drawstring(const char *str) | ||
285 | { | ||
286 | xmon_fputs(str, xmon_stdout); | ||
287 | } | ||
diff --git a/arch/powerpc/xmon/subr_prf.c b/arch/powerpc/xmon/subr_prf.c deleted file mode 100644 index b48738c6dd33..000000000000 --- a/arch/powerpc/xmon/subr_prf.c +++ /dev/null | |||
@@ -1,54 +0,0 @@ | |||
1 | /* | ||
2 | * Written by Cort Dougan to replace the version originally used | ||
3 | * by Paul Mackerras, which came from NetBSD and thus had copyright | ||
4 | * conflicts with Linux. | ||
5 | * | ||
6 | * This file makes liberal use of the standard linux utility | ||
7 | * routines to reduce the size of the binary. We assume we can | ||
8 | * trust some parts of Linux inside the debugger. | ||
9 | * -- Cort (cort@cs.nmt.edu) | ||
10 | * | ||
11 | * Copyright (C) 1999 Cort Dougan. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version | ||
16 | * 2 of the License, or (at your option) any later version. | ||
17 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/string.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <stdarg.h> | ||
23 | #include "nonstdio.h" | ||
24 | |||
25 | extern int xmon_write(void *, void *, int); | ||
26 | |||
27 | void xmon_vfprintf(void *f, const char *fmt, va_list ap) | ||
28 | { | ||
29 | static char xmon_buf[2048]; | ||
30 | int n; | ||
31 | |||
32 | n = vsprintf(xmon_buf, fmt, ap); | ||
33 | xmon_write(f, xmon_buf, n); | ||
34 | } | ||
35 | |||
36 | void xmon_printf(const char *fmt, ...) | ||
37 | { | ||
38 | va_list ap; | ||
39 | |||
40 | va_start(ap, fmt); | ||
41 | xmon_vfprintf(stdout, fmt, ap); | ||
42 | va_end(ap); | ||
43 | } | ||
44 | EXPORT_SYMBOL(xmon_printf); | ||
45 | |||
46 | void xmon_fprintf(void *f, const char *fmt, ...) | ||
47 | { | ||
48 | va_list ap; | ||
49 | |||
50 | va_start(ap, fmt); | ||
51 | xmon_vfprintf(f, fmt, ap); | ||
52 | va_end(ap); | ||
53 | } | ||
54 | |||
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 1124f1146202..cfcb2a56d662 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Routines providing a simple monitor for use on the PowerMac. | 2 | * Routines providing a simple monitor for use on the PowerMac. |
3 | * | 3 | * |
4 | * Copyright (C) 1996 Paul Mackerras. | 4 | * Copyright (C) 1996-2005 Paul Mackerras. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License | 7 | * modify it under the terms of the GNU General Public License |
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/kallsyms.h> | 18 | #include <linux/kallsyms.h> |
19 | #include <linux/cpumask.h> | 19 | #include <linux/cpumask.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/sysrq.h> | ||
21 | 22 | ||
22 | #include <asm/ptrace.h> | 23 | #include <asm/ptrace.h> |
23 | #include <asm/string.h> | 24 | #include <asm/string.h> |
@@ -144,15 +145,10 @@ static void xmon_print_symbol(unsigned long address, const char *mid, | |||
144 | static const char *getvecname(unsigned long vec); | 145 | static const char *getvecname(unsigned long vec); |
145 | 146 | ||
146 | extern int print_insn_powerpc(unsigned long, unsigned long, int); | 147 | extern int print_insn_powerpc(unsigned long, unsigned long, int); |
147 | extern void printf(const char *fmt, ...); | ||
148 | extern void xmon_vfprintf(void *f, const char *fmt, va_list ap); | ||
149 | extern int xmon_putc(int c, void *f); | ||
150 | extern int putchar(int ch); | ||
151 | 148 | ||
152 | extern void xmon_enter(void); | 149 | extern void xmon_enter(void); |
153 | extern void xmon_leave(void); | 150 | extern void xmon_leave(void); |
154 | 151 | ||
155 | extern int xmon_read_poll(void); | ||
156 | extern long setjmp(long *); | 152 | extern long setjmp(long *); |
157 | extern void longjmp(long *, long); | 153 | extern void longjmp(long *, long); |
158 | extern void xmon_save_regs(struct pt_regs *); | 154 | extern void xmon_save_regs(struct pt_regs *); |
@@ -748,7 +744,6 @@ cmds(struct pt_regs *excp) | |||
748 | printf("%x:", smp_processor_id()); | 744 | printf("%x:", smp_processor_id()); |
749 | #endif /* CONFIG_SMP */ | 745 | #endif /* CONFIG_SMP */ |
750 | printf("mon> "); | 746 | printf("mon> "); |
751 | fflush(stdout); | ||
752 | flush_input(); | 747 | flush_input(); |
753 | termch = 0; | 748 | termch = 0; |
754 | cmd = skipbl(); | 749 | cmd = skipbl(); |
@@ -1797,7 +1792,7 @@ memex(void) | |||
1797 | for(;;){ | 1792 | for(;;){ |
1798 | if (!mnoread) | 1793 | if (!mnoread) |
1799 | n = mread(adrs, val, size); | 1794 | n = mread(adrs, val, size); |
1800 | printf("%.16x%c", adrs, brev? 'r': ' '); | 1795 | printf(REG"%c", adrs, brev? 'r': ' '); |
1801 | if (!mnoread) { | 1796 | if (!mnoread) { |
1802 | if (brev) | 1797 | if (brev) |
1803 | byterev(val, size); | 1798 | byterev(val, size); |
@@ -1976,17 +1971,18 @@ prdump(unsigned long adrs, long ndump) | |||
1976 | nr = mread(adrs, temp, r); | 1971 | nr = mread(adrs, temp, r); |
1977 | adrs += nr; | 1972 | adrs += nr; |
1978 | for (m = 0; m < r; ++m) { | 1973 | for (m = 0; m < r; ++m) { |
1979 | if ((m & 7) == 0 && m > 0) | 1974 | if ((m & (sizeof(long) - 1)) == 0 && m > 0) |
1980 | putchar(' '); | 1975 | putchar(' '); |
1981 | if (m < nr) | 1976 | if (m < nr) |
1982 | printf("%.2x", temp[m]); | 1977 | printf("%.2x", temp[m]); |
1983 | else | 1978 | else |
1984 | printf("%s", fault_chars[fault_type]); | 1979 | printf("%s", fault_chars[fault_type]); |
1985 | } | 1980 | } |
1986 | if (m <= 8) | 1981 | for (; m < 16; ++m) { |
1987 | printf(" "); | 1982 | if ((m & (sizeof(long) - 1)) == 0) |
1988 | for (; m < 16; ++m) | 1983 | putchar(' '); |
1989 | printf(" "); | 1984 | printf(" "); |
1985 | } | ||
1990 | printf(" |"); | 1986 | printf(" |"); |
1991 | for (m = 0; m < r; ++m) { | 1987 | for (m = 0; m < r; ++m) { |
1992 | if (m < nr) { | 1988 | if (m < nr) { |
@@ -2151,7 +2147,6 @@ memzcan(void) | |||
2151 | ok = mread(a, &v, 1); | 2147 | ok = mread(a, &v, 1); |
2152 | if (ok && !ook) { | 2148 | if (ok && !ook) { |
2153 | printf("%.8x .. ", a); | 2149 | printf("%.8x .. ", a); |
2154 | fflush(stdout); | ||
2155 | } else if (!ok && ook) | 2150 | } else if (!ok && ook) |
2156 | printf("%.8x\n", a - mskip); | 2151 | printf("%.8x\n", a - mskip); |
2157 | ook = ok; | 2152 | ook = ok; |
@@ -2372,7 +2367,7 @@ int | |||
2372 | inchar(void) | 2367 | inchar(void) |
2373 | { | 2368 | { |
2374 | if (lineptr == NULL || *lineptr == 0) { | 2369 | if (lineptr == NULL || *lineptr == 0) { |
2375 | if (fgets(line, sizeof(line), stdin) == NULL) { | 2370 | if (xmon_gets(line, sizeof(line)) == NULL) { |
2376 | lineptr = NULL; | 2371 | lineptr = NULL; |
2377 | return EOF; | 2372 | return EOF; |
2378 | } | 2373 | } |
@@ -2526,4 +2521,29 @@ void xmon_init(int enable) | |||
2526 | __debugger_dabr_match = NULL; | 2521 | __debugger_dabr_match = NULL; |
2527 | __debugger_fault_handler = NULL; | 2522 | __debugger_fault_handler = NULL; |
2528 | } | 2523 | } |
2524 | xmon_map_scc(); | ||
2525 | } | ||
2526 | |||
2527 | #ifdef CONFIG_MAGIC_SYSRQ | ||
2528 | static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs, | ||
2529 | struct tty_struct *tty) | ||
2530 | { | ||
2531 | /* ensure xmon is enabled */ | ||
2532 | xmon_init(1); | ||
2533 | debugger(pt_regs); | ||
2534 | } | ||
2535 | |||
2536 | static struct sysrq_key_op sysrq_xmon_op = | ||
2537 | { | ||
2538 | .handler = sysrq_handle_xmon, | ||
2539 | .help_msg = "Xmon", | ||
2540 | .action_msg = "Entering xmon", | ||
2541 | }; | ||
2542 | |||
2543 | static int __init setup_xmon_sysrq(void) | ||
2544 | { | ||
2545 | register_sysrq_key('x', &sysrq_xmon_op); | ||
2546 | return 0; | ||
2529 | } | 2547 | } |
2548 | __initcall(setup_xmon_sysrq); | ||
2549 | #endif /* CONFIG_MAGIC_SYSRQ */ | ||
diff --git a/arch/ppc/boot/include/of1275.h b/arch/ppc/boot/include/of1275.h index 69173df76db0..4ed88acfa73a 100644 --- a/arch/ppc/boot/include/of1275.h +++ b/arch/ppc/boot/include/of1275.h | |||
@@ -19,6 +19,9 @@ extern prom_entry of_prom_entry; | |||
19 | 19 | ||
20 | /* function declarations */ | 20 | /* function declarations */ |
21 | 21 | ||
22 | int call_prom(const char *service, int nargs, int nret, ...); | ||
23 | int call_prom_ret(const char *service, int nargs, int nret, | ||
24 | unsigned int *rets, ...); | ||
22 | void * claim(unsigned int virt, unsigned int size, unsigned int align); | 25 | void * claim(unsigned int virt, unsigned int size, unsigned int align); |
23 | int map(unsigned int phys, unsigned int virt, unsigned int size); | 26 | int map(unsigned int phys, unsigned int virt, unsigned int size); |
24 | void enter(void); | 27 | void enter(void); |
diff --git a/arch/ppc/boot/of1275/Makefile b/arch/ppc/boot/of1275/Makefile index 02e6f235d7cb..0b979c004972 100644 --- a/arch/ppc/boot/of1275/Makefile +++ b/arch/ppc/boot/of1275/Makefile | |||
@@ -3,4 +3,4 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | lib-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o \ | 5 | lib-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o \ |
6 | ofstdio.o read.o release.o write.o map.o | 6 | ofstdio.o read.o release.o write.o map.o call_prom.o |
diff --git a/arch/ppc/boot/of1275/call_prom.c b/arch/ppc/boot/of1275/call_prom.c new file mode 100644 index 000000000000..9479a3a2b8c7 --- /dev/null +++ b/arch/ppc/boot/of1275/call_prom.c | |||
@@ -0,0 +1,74 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996-2005 Paul Mackerras. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include "of1275.h" | ||
11 | #include <stdarg.h> | ||
12 | |||
13 | int call_prom(const char *service, int nargs, int nret, ...) | ||
14 | { | ||
15 | int i; | ||
16 | struct prom_args { | ||
17 | const char *service; | ||
18 | int nargs; | ||
19 | int nret; | ||
20 | unsigned int args[12]; | ||
21 | } args; | ||
22 | va_list list; | ||
23 | |||
24 | args.service = service; | ||
25 | args.nargs = nargs; | ||
26 | args.nret = nret; | ||
27 | |||
28 | va_start(list, nret); | ||
29 | for (i = 0; i < nargs; i++) | ||
30 | args.args[i] = va_arg(list, unsigned int); | ||
31 | va_end(list); | ||
32 | |||
33 | for (i = 0; i < nret; i++) | ||
34 | args.args[nargs+i] = 0; | ||
35 | |||
36 | if (of_prom_entry(&args) < 0) | ||
37 | return -1; | ||
38 | |||
39 | return (nret > 0)? args.args[nargs]: 0; | ||
40 | } | ||
41 | |||
42 | int call_prom_ret(const char *service, int nargs, int nret, | ||
43 | unsigned int *rets, ...) | ||
44 | { | ||
45 | int i; | ||
46 | struct prom_args { | ||
47 | const char *service; | ||
48 | int nargs; | ||
49 | int nret; | ||
50 | unsigned int args[12]; | ||
51 | } args; | ||
52 | va_list list; | ||
53 | |||
54 | args.service = service; | ||
55 | args.nargs = nargs; | ||
56 | args.nret = nret; | ||
57 | |||
58 | va_start(list, rets); | ||
59 | for (i = 0; i < nargs; i++) | ||
60 | args.args[i] = va_arg(list, unsigned int); | ||
61 | va_end(list); | ||
62 | |||
63 | for (i = 0; i < nret; i++) | ||
64 | args.args[nargs+i] = 0; | ||
65 | |||
66 | if (of_prom_entry(&args) < 0) | ||
67 | return -1; | ||
68 | |||
69 | if (rets != (void *) 0) | ||
70 | for (i = 1; i < nret; ++i) | ||
71 | rets[i-1] = args.args[nargs+i]; | ||
72 | |||
73 | return (nret > 0)? args.args[nargs]: 0; | ||
74 | } | ||
diff --git a/arch/ppc/boot/of1275/claim.c b/arch/ppc/boot/of1275/claim.c index 13169a5c4339..1ed3aeeff8ae 100644 --- a/arch/ppc/boot/of1275/claim.c +++ b/arch/ppc/boot/of1275/claim.c | |||
@@ -9,27 +9,84 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include "of1275.h" | 11 | #include "of1275.h" |
12 | #include "nonstdio.h" | ||
12 | 13 | ||
13 | void * | 14 | /* |
14 | claim(unsigned int virt, unsigned int size, unsigned int align) | 15 | * Older OF's require that when claiming a specific range of addresses, |
16 | * we claim the physical space in the /memory node and the virtual | ||
17 | * space in the chosen mmu node, and then do a map operation to | ||
18 | * map virtual to physical. | ||
19 | */ | ||
20 | static int need_map = -1; | ||
21 | static ihandle chosen_mmu; | ||
22 | static phandle memory; | ||
23 | |||
24 | /* returns true if s2 is a prefix of s1 */ | ||
25 | static int string_match(const char *s1, const char *s2) | ||
26 | { | ||
27 | for (; *s2; ++s2) | ||
28 | if (*s1++ != *s2) | ||
29 | return 0; | ||
30 | return 1; | ||
31 | } | ||
32 | |||
33 | static int check_of_version(void) | ||
34 | { | ||
35 | phandle oprom, chosen; | ||
36 | char version[64]; | ||
37 | |||
38 | oprom = finddevice("/openprom"); | ||
39 | if (oprom == OF_INVALID_HANDLE) | ||
40 | return 0; | ||
41 | if (getprop(oprom, "model", version, sizeof(version)) <= 0) | ||
42 | return 0; | ||
43 | version[sizeof(version)-1] = 0; | ||
44 | printf("OF version = '%s'\n", version); | ||
45 | if (!string_match(version, "Open Firmware, 1.") | ||
46 | && !string_match(version, "FirmWorks,3.")) | ||
47 | return 0; | ||
48 | chosen = finddevice("/chosen"); | ||
49 | if (chosen == OF_INVALID_HANDLE) { | ||
50 | chosen = finddevice("/chosen@0"); | ||
51 | if (chosen == OF_INVALID_HANDLE) { | ||
52 | printf("no chosen\n"); | ||
53 | return 0; | ||
54 | } | ||
55 | } | ||
56 | if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { | ||
57 | printf("no mmu\n"); | ||
58 | return 0; | ||
59 | } | ||
60 | memory = (ihandle) call_prom("open", 1, 1, "/memory"); | ||
61 | if (memory == OF_INVALID_HANDLE) { | ||
62 | memory = (ihandle) call_prom("open", 1, 1, "/memory@0"); | ||
63 | if (memory == OF_INVALID_HANDLE) { | ||
64 | printf("no memory node\n"); | ||
65 | return 0; | ||
66 | } | ||
67 | } | ||
68 | printf("old OF detected\n"); | ||
69 | return 1; | ||
70 | } | ||
71 | |||
72 | void *claim(unsigned int virt, unsigned int size, unsigned int align) | ||
15 | { | 73 | { |
16 | struct prom_args { | 74 | int ret; |
17 | char *service; | 75 | unsigned int result; |
18 | int nargs; | ||
19 | int nret; | ||
20 | unsigned int virt; | ||
21 | unsigned int size; | ||
22 | unsigned int align; | ||
23 | void *ret; | ||
24 | } args; | ||
25 | 76 | ||
26 | args.service = "claim"; | 77 | if (need_map < 0) |
27 | args.nargs = 3; | 78 | need_map = check_of_version(); |
28 | args.nret = 1; | 79 | if (align || !need_map) |
29 | args.virt = virt; | 80 | return (void *) call_prom("claim", 3, 1, virt, size, align); |
30 | args.size = size; | 81 | |
31 | args.align = align; | 82 | ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory, |
32 | args.ret = (void *) 0; | 83 | align, size, virt); |
33 | (*of_prom_entry)(&args); | 84 | if (ret != 0 || result == -1) |
34 | return args.ret; | 85 | return (void *) -1; |
86 | ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, | ||
87 | align, size, virt); | ||
88 | /* 0x12 == coherent + read/write */ | ||
89 | ret = call_prom("call-method", 6, 1, "map", chosen_mmu, | ||
90 | 0x12, size, virt, virt); | ||
91 | return virt; | ||
35 | } | 92 | } |
diff --git a/arch/ppc/boot/of1275/finddevice.c b/arch/ppc/boot/of1275/finddevice.c index 2c0f7cbb793e..0dcb1201b772 100644 --- a/arch/ppc/boot/of1275/finddevice.c +++ b/arch/ppc/boot/of1275/finddevice.c | |||
@@ -10,22 +10,7 @@ | |||
10 | 10 | ||
11 | #include "of1275.h" | 11 | #include "of1275.h" |
12 | 12 | ||
13 | phandle | 13 | phandle finddevice(const char *name) |
14 | finddevice(const char *name) | ||
15 | { | 14 | { |
16 | struct prom_args { | 15 | return (phandle) call_prom("finddevice", 1, 1, name); |
17 | char *service; | ||
18 | int nargs; | ||
19 | int nret; | ||
20 | const char *devspec; | ||
21 | phandle device; | ||
22 | } args; | ||
23 | |||
24 | args.service = "finddevice"; | ||
25 | args.nargs = 1; | ||
26 | args.nret = 1; | ||
27 | args.devspec = name; | ||
28 | args.device = OF_INVALID_HANDLE; | ||
29 | (*of_prom_entry)(&args); | ||
30 | return args.device; | ||
31 | } | 16 | } |
diff --git a/arch/ppc/boot/openfirmware/Makefile b/arch/ppc/boot/openfirmware/Makefile index 03415238fabf..83a6433459ce 100644 --- a/arch/ppc/boot/openfirmware/Makefile +++ b/arch/ppc/boot/openfirmware/Makefile | |||
@@ -80,8 +80,7 @@ $(obj)/note: $(utils)/mknote FORCE | |||
80 | $(call if_changed,mknote) | 80 | $(call if_changed,mknote) |
81 | 81 | ||
82 | 82 | ||
83 | $(obj)/coffcrt0.o: EXTRA_AFLAGS := -traditional -DXCOFF | 83 | $(obj)/coffcrt0.o: EXTRA_AFLAGS := -DXCOFF |
84 | $(obj)/crt0.o: EXTRA_AFLAGS := -traditional | ||
85 | targets += coffcrt0.o crt0.o | 84 | targets += coffcrt0.o crt0.o |
86 | $(obj)/coffcrt0.o $(obj)/crt0.o: $(common)/crt0.S FORCE | 85 | $(obj)/coffcrt0.o $(obj)/crt0.o: $(common)/crt0.S FORCE |
87 | $(call if_changed_dep,as_o_S) | 86 | $(call if_changed_dep,as_o_S) |
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index 76a55a438f23..17a4da65e275 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile | |||
@@ -12,7 +12,7 @@ extra-$(CONFIG_6xx) += idle_6xx.o | |||
12 | extra-$(CONFIG_POWER4) += idle_power4.o | 12 | extra-$(CONFIG_POWER4) += idle_power4.o |
13 | extra-y += vmlinux.lds | 13 | extra-y += vmlinux.lds |
14 | 14 | ||
15 | obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ | 15 | obj-y := entry.o traps.o idle.o time.o misc.o \ |
16 | process.o align.o \ | 16 | process.o align.o \ |
17 | setup.o \ | 17 | setup.o \ |
18 | ppc_htab.o | 18 | ppc_htab.o |
@@ -38,8 +38,7 @@ endif | |||
38 | # These are here while we do the architecture merge | 38 | # These are here while we do the architecture merge |
39 | 39 | ||
40 | else | 40 | else |
41 | obj-y := irq.o idle.o \ | 41 | obj-y := idle.o align.o |
42 | align.o | ||
43 | obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o | 42 | obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o |
44 | obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o | 43 | obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o |
45 | obj-$(CONFIG_MODULES) += module.o | 44 | obj-$(CONFIG_MODULES) += module.o |
diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h index aeb349b47af3..f3d274c6b231 100644 --- a/arch/ppc/kernel/head_booke.h +++ b/arch/ppc/kernel/head_booke.h | |||
@@ -358,6 +358,6 @@ label: | |||
358 | NORMAL_EXCEPTION_PROLOG; \ | 358 | NORMAL_EXCEPTION_PROLOG; \ |
359 | bne load_up_fpu; /* if from user, just load it up */ \ | 359 | bne load_up_fpu; /* if from user, just load it up */ \ |
360 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | 360 | addi r3,r1,STACK_FRAME_OVERHEAD; \ |
361 | EXC_XFER_EE_LITE(0x800, KernelFP) | 361 | EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception) |
362 | 362 | ||
363 | #endif /* __HEAD_BOOKE_H__ */ | 363 | #endif /* __HEAD_BOOKE_H__ */ |
diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c deleted file mode 100644 index fbb2b9f8922c..000000000000 --- a/arch/ppc/kernel/irq.c +++ /dev/null | |||
@@ -1,165 +0,0 @@ | |||
1 | /* | ||
2 | * arch/ppc/kernel/irq.c | ||
3 | * | ||
4 | * Derived from arch/i386/kernel/irq.c | ||
5 | * Copyright (C) 1992 Linus Torvalds | ||
6 | * Adapted from arch/i386 by Gary Thomas | ||
7 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | ||
8 | * Updated and modified by Cort Dougan <cort@fsmlabs.com> | ||
9 | * Copyright (C) 1996-2001 Cort Dougan | ||
10 | * Adapted for Power Macintosh by Paul Mackerras | ||
11 | * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) | ||
12 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
13 | * | ||
14 | * This file contains the code used by various IRQ handling routines: | ||
15 | * asking for different IRQ's should be done through these routines | ||
16 | * instead of just grabbing them. Thus setups with different IRQ numbers | ||
17 | * shouldn't result in any weird surprises, and installing new handlers | ||
18 | * should be easier. | ||
19 | * | ||
20 | * The MPC8xx has an interrupt mask in the SIU. If a bit is set, the | ||
21 | * interrupt is _enabled_. As expected, IRQ0 is bit 0 in the 32-bit | ||
22 | * mask register (of which only 16 are defined), hence the weird shifting | ||
23 | * and complement of the cached_irq_mask. I want to be able to stuff | ||
24 | * this right into the SIU SMASK register. | ||
25 | * Many of the prep/chrp functions are conditional compiled on CONFIG_8xx | ||
26 | * to reduce code space and undefined function references. | ||
27 | */ | ||
28 | |||
29 | #include <linux/errno.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/threads.h> | ||
32 | #include <linux/kernel_stat.h> | ||
33 | #include <linux/signal.h> | ||
34 | #include <linux/sched.h> | ||
35 | #include <linux/ptrace.h> | ||
36 | #include <linux/ioport.h> | ||
37 | #include <linux/interrupt.h> | ||
38 | #include <linux/timex.h> | ||
39 | #include <linux/config.h> | ||
40 | #include <linux/init.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/pci.h> | ||
43 | #include <linux/delay.h> | ||
44 | #include <linux/irq.h> | ||
45 | #include <linux/proc_fs.h> | ||
46 | #include <linux/random.h> | ||
47 | #include <linux/seq_file.h> | ||
48 | #include <linux/cpumask.h> | ||
49 | #include <linux/profile.h> | ||
50 | #include <linux/bitops.h> | ||
51 | |||
52 | #include <asm/uaccess.h> | ||
53 | #include <asm/system.h> | ||
54 | #include <asm/io.h> | ||
55 | #include <asm/pgtable.h> | ||
56 | #include <asm/irq.h> | ||
57 | #include <asm/cache.h> | ||
58 | #include <asm/prom.h> | ||
59 | #include <asm/ptrace.h> | ||
60 | #include <asm/machdep.h> | ||
61 | |||
62 | #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) | ||
63 | |||
64 | extern atomic_t ipi_recv; | ||
65 | extern atomic_t ipi_sent; | ||
66 | |||
67 | #define MAXCOUNT 10000000 | ||
68 | |||
69 | int ppc_spurious_interrupts = 0; | ||
70 | struct irqaction *ppc_irq_action[NR_IRQS]; | ||
71 | unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; | ||
72 | unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; | ||
73 | atomic_t ppc_n_lost_interrupts; | ||
74 | |||
75 | #ifdef CONFIG_TAU_INT | ||
76 | extern int tau_initialized; | ||
77 | extern int tau_interrupts(int); | ||
78 | #endif | ||
79 | |||
80 | int show_interrupts(struct seq_file *p, void *v) | ||
81 | { | ||
82 | int i = *(loff_t *) v, j; | ||
83 | struct irqaction * action; | ||
84 | unsigned long flags; | ||
85 | |||
86 | if (i == 0) { | ||
87 | seq_puts(p, " "); | ||
88 | for (j=0; j<NR_CPUS; j++) | ||
89 | if (cpu_online(j)) | ||
90 | seq_printf(p, "CPU%d ", j); | ||
91 | seq_putc(p, '\n'); | ||
92 | } | ||
93 | |||
94 | if (i < NR_IRQS) { | ||
95 | spin_lock_irqsave(&irq_desc[i].lock, flags); | ||
96 | action = irq_desc[i].action; | ||
97 | if ( !action || !action->handler ) | ||
98 | goto skip; | ||
99 | seq_printf(p, "%3d: ", i); | ||
100 | #ifdef CONFIG_SMP | ||
101 | for (j = 0; j < NR_CPUS; j++) | ||
102 | if (cpu_online(j)) | ||
103 | seq_printf(p, "%10u ", | ||
104 | kstat_cpu(j).irqs[i]); | ||
105 | #else | ||
106 | seq_printf(p, "%10u ", kstat_irqs(i)); | ||
107 | #endif /* CONFIG_SMP */ | ||
108 | if (irq_desc[i].handler) | ||
109 | seq_printf(p, " %s ", irq_desc[i].handler->typename); | ||
110 | else | ||
111 | seq_puts(p, " None "); | ||
112 | seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge "); | ||
113 | seq_printf(p, " %s", action->name); | ||
114 | for (action = action->next; action; action = action->next) | ||
115 | seq_printf(p, ", %s", action->name); | ||
116 | seq_putc(p, '\n'); | ||
117 | skip: | ||
118 | spin_unlock_irqrestore(&irq_desc[i].lock, flags); | ||
119 | } else if (i == NR_IRQS) { | ||
120 | #ifdef CONFIG_TAU_INT | ||
121 | if (tau_initialized){ | ||
122 | seq_puts(p, "TAU: "); | ||
123 | for (j = 0; j < NR_CPUS; j++) | ||
124 | if (cpu_online(j)) | ||
125 | seq_printf(p, "%10u ", tau_interrupts(j)); | ||
126 | seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); | ||
127 | } | ||
128 | #endif | ||
129 | #if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE) | ||
130 | /* should this be per processor send/receive? */ | ||
131 | seq_printf(p, "IPI (recv/sent): %10u/%u\n", | ||
132 | atomic_read(&ipi_recv), atomic_read(&ipi_sent)); | ||
133 | #endif | ||
134 | seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); | ||
135 | } | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | void do_IRQ(struct pt_regs *regs) | ||
140 | { | ||
141 | int irq, first = 1; | ||
142 | irq_enter(); | ||
143 | |||
144 | /* | ||
145 | * Every platform is required to implement ppc_md.get_irq. | ||
146 | * This function will either return an irq number or -1 to | ||
147 | * indicate there are no more pending. But the first time | ||
148 | * through the loop this means there wasn't and IRQ pending. | ||
149 | * The value -2 is for buggy hardware and means that this IRQ | ||
150 | * has already been handled. -- Tom | ||
151 | */ | ||
152 | while ((irq = ppc_md.get_irq(regs)) >= 0) { | ||
153 | __do_IRQ(irq, regs); | ||
154 | first = 0; | ||
155 | } | ||
156 | if (irq != -2 && first) | ||
157 | /* That's not SMP safe ... but who cares ? */ | ||
158 | ppc_spurious_interrupts++; | ||
159 | irq_exit(); | ||
160 | } | ||
161 | |||
162 | void __init init_IRQ(void) | ||
163 | { | ||
164 | ppc_md.init_IRQ(); | ||
165 | } | ||
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index ae6af29938a1..5e61124581d0 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S | |||
@@ -497,9 +497,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | |||
497 | * and invalidate the corresponding instruction cache blocks. | 497 | * and invalidate the corresponding instruction cache blocks. |
498 | * This is a no-op on the 601. | 498 | * This is a no-op on the 601. |
499 | * | 499 | * |
500 | * flush_icache_range(unsigned long start, unsigned long stop) | 500 | * __flush_icache_range(unsigned long start, unsigned long stop) |
501 | */ | 501 | */ |
502 | _GLOBAL(flush_icache_range) | 502 | _GLOBAL(__flush_icache_range) |
503 | BEGIN_FTR_SECTION | 503 | BEGIN_FTR_SECTION |
504 | blr /* for 601, do nothing */ | 504 | blr /* for 601, do nothing */ |
505 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 505 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) |
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index e0ca61b37f4f..66073f775193 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <asm/btext.h> | 46 | #include <asm/btext.h> |
47 | #include <asm/div64.h> | 47 | #include <asm/div64.h> |
48 | #include <asm/xmon.h> | 48 | #include <asm/xmon.h> |
49 | #include <asm/signal.h> | ||
49 | 50 | ||
50 | #ifdef CONFIG_8xx | 51 | #ifdef CONFIG_8xx |
51 | #include <asm/commproc.h> | 52 | #include <asm/commproc.h> |
@@ -57,7 +58,6 @@ extern void machine_check_exception(struct pt_regs *regs); | |||
57 | extern void alignment_exception(struct pt_regs *regs); | 58 | extern void alignment_exception(struct pt_regs *regs); |
58 | extern void program_check_exception(struct pt_regs *regs); | 59 | extern void program_check_exception(struct pt_regs *regs); |
59 | extern void single_step_exception(struct pt_regs *regs); | 60 | extern void single_step_exception(struct pt_regs *regs); |
60 | extern int do_signal(sigset_t *, struct pt_regs *); | ||
61 | extern int pmac_newworld; | 61 | extern int pmac_newworld; |
62 | extern int sys_sigreturn(struct pt_regs *regs); | 62 | extern int sys_sigreturn(struct pt_regs *regs); |
63 | 63 | ||
@@ -78,7 +78,6 @@ EXPORT_SYMBOL(program_check_exception); | |||
78 | EXPORT_SYMBOL(single_step_exception); | 78 | EXPORT_SYMBOL(single_step_exception); |
79 | EXPORT_SYMBOL(sys_sigreturn); | 79 | EXPORT_SYMBOL(sys_sigreturn); |
80 | EXPORT_SYMBOL(ppc_n_lost_interrupts); | 80 | EXPORT_SYMBOL(ppc_n_lost_interrupts); |
81 | EXPORT_SYMBOL(ppc_lost_interrupts); | ||
82 | 81 | ||
83 | EXPORT_SYMBOL(ISA_DMA_THRESHOLD); | 82 | EXPORT_SYMBOL(ISA_DMA_THRESHOLD); |
84 | EXPORT_SYMBOL(DMA_MODE_READ); | 83 | EXPORT_SYMBOL(DMA_MODE_READ); |
@@ -176,6 +175,7 @@ EXPORT_SYMBOL(pci_bus_to_phys); | |||
176 | #endif /* CONFIG_PCI */ | 175 | #endif /* CONFIG_PCI */ |
177 | 176 | ||
178 | #ifdef CONFIG_NOT_COHERENT_CACHE | 177 | #ifdef CONFIG_NOT_COHERENT_CACHE |
178 | extern void flush_dcache_all(void); | ||
179 | EXPORT_SYMBOL(flush_dcache_all); | 179 | EXPORT_SYMBOL(flush_dcache_all); |
180 | #endif | 180 | #endif |
181 | 181 | ||
@@ -217,9 +217,6 @@ EXPORT_SYMBOL(adb_try_handler_change); | |||
217 | EXPORT_SYMBOL(cuda_request); | 217 | EXPORT_SYMBOL(cuda_request); |
218 | EXPORT_SYMBOL(cuda_poll); | 218 | EXPORT_SYMBOL(cuda_poll); |
219 | #endif /* CONFIG_ADB_CUDA */ | 219 | #endif /* CONFIG_ADB_CUDA */ |
220 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
221 | EXPORT_SYMBOL(_machine); | ||
222 | #endif | ||
223 | #ifdef CONFIG_PPC_PMAC | 220 | #ifdef CONFIG_PPC_PMAC |
224 | EXPORT_SYMBOL(sys_ctrler); | 221 | EXPORT_SYMBOL(sys_ctrler); |
225 | EXPORT_SYMBOL(pmac_newworld); | 222 | EXPORT_SYMBOL(pmac_newworld); |
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 6bcb85d2b7fd..dc55e1abc45b 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c | |||
@@ -76,6 +76,7 @@ unsigned int DMA_MODE_WRITE; | |||
76 | 76 | ||
77 | #ifdef CONFIG_PPC_MULTIPLATFORM | 77 | #ifdef CONFIG_PPC_MULTIPLATFORM |
78 | int _machine = 0; | 78 | int _machine = 0; |
79 | EXPORT_SYMBOL(_machine); | ||
79 | 80 | ||
80 | extern void prep_init(unsigned long r3, unsigned long r4, | 81 | extern void prep_init(unsigned long r3, unsigned long r4, |
81 | unsigned long r5, unsigned long r6, unsigned long r7); | 82 | unsigned long r5, unsigned long r6, unsigned long r7); |
diff --git a/arch/ppc/platforms/pmac_pic.c b/arch/ppc/platforms/pmac_pic.c index 9f2d95ea8564..4742bf609357 100644 --- a/arch/ppc/platforms/pmac_pic.c +++ b/arch/ppc/platforms/pmac_pic.c | |||
@@ -75,6 +75,9 @@ static DEFINE_SPINLOCK(pmac_pic_lock); | |||
75 | #define GATWICK_IRQ_POOL_SIZE 10 | 75 | #define GATWICK_IRQ_POOL_SIZE 10 |
76 | static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; | 76 | static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; |
77 | 77 | ||
78 | #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) | ||
79 | static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; | ||
80 | |||
78 | /* | 81 | /* |
79 | * Mark an irq as "lost". This is only used on the pmac | 82 | * Mark an irq as "lost". This is only used on the pmac |
80 | * since it can lose interrupts (see pmac_set_irq_mask). | 83 | * since it can lose interrupts (see pmac_set_irq_mask). |
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c index 067d7d53b81e..4415748071dc 100644 --- a/arch/ppc/platforms/prep_setup.c +++ b/arch/ppc/platforms/prep_setup.c | |||
@@ -61,6 +61,15 @@ | |||
61 | #include <asm/pci-bridge.h> | 61 | #include <asm/pci-bridge.h> |
62 | #include <asm/todc.h> | 62 | #include <asm/todc.h> |
63 | 63 | ||
64 | /* prep registers for L2 */ | ||
65 | #define CACHECRBA 0x80000823 /* Cache configuration register address */ | ||
66 | #define L2CACHE_MASK 0x03 /* Mask for 2 L2 Cache bits */ | ||
67 | #define L2CACHE_512KB 0x00 /* 512KB */ | ||
68 | #define L2CACHE_256KB 0x01 /* 256KB */ | ||
69 | #define L2CACHE_1MB 0x02 /* 1MB */ | ||
70 | #define L2CACHE_NONE 0x03 /* NONE */ | ||
71 | #define L2CACHE_PARITY 0x08 /* Mask for L2 Cache Parity Protected bit */ | ||
72 | |||
64 | TODC_ALLOC(); | 73 | TODC_ALLOC(); |
65 | 74 | ||
66 | unsigned char ucSystemType; | 75 | unsigned char ucSystemType; |
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig index 29552348e581..c9d32db9d76a 100644 --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig | |||
@@ -297,6 +297,10 @@ config HAVE_ARCH_EARLY_PFN_TO_NID | |||
297 | def_bool y | 297 | def_bool y |
298 | depends on NEED_MULTIPLE_NODES | 298 | depends on NEED_MULTIPLE_NODES |
299 | 299 | ||
300 | config ARCH_MEMORY_PROBE | ||
301 | def_bool y | ||
302 | depends on MEMORY_HOTPLUG | ||
303 | |||
300 | # Some NUMA nodes have memory ranges that span | 304 | # Some NUMA nodes have memory ranges that span |
301 | # other nodes. Even though a pfn is valid and | 305 | # other nodes. Even though a pfn is valid and |
302 | # between a node's start and end pfns, it may not | 306 | # between a node's start and end pfns, it may not |
diff --git a/arch/ppc64/boot/addRamDisk.c b/arch/ppc64/boot/addRamDisk.c index 7f2c09473394..c02a99952be7 100644 --- a/arch/ppc64/boot/addRamDisk.c +++ b/arch/ppc64/boot/addRamDisk.c | |||
@@ -5,11 +5,59 @@ | |||
5 | #include <sys/types.h> | 5 | #include <sys/types.h> |
6 | #include <sys/stat.h> | 6 | #include <sys/stat.h> |
7 | #include <string.h> | 7 | #include <string.h> |
8 | #include <elf.h> | ||
8 | 9 | ||
9 | #define ElfHeaderSize (64 * 1024) | 10 | #define ElfHeaderSize (64 * 1024) |
10 | #define ElfPages (ElfHeaderSize / 4096) | 11 | #define ElfPages (ElfHeaderSize / 4096) |
11 | #define KERNELBASE (0xc000000000000000) | 12 | #define KERNELBASE (0xc000000000000000) |
13 | #define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1))) | ||
12 | 14 | ||
15 | struct addr_range { | ||
16 | unsigned long long addr; | ||
17 | unsigned long memsize; | ||
18 | unsigned long offset; | ||
19 | }; | ||
20 | |||
21 | static int check_elf64(void *p, int size, struct addr_range *r) | ||
22 | { | ||
23 | Elf64_Ehdr *elf64 = p; | ||
24 | Elf64_Phdr *elf64ph; | ||
25 | |||
26 | if (elf64->e_ident[EI_MAG0] != ELFMAG0 || | ||
27 | elf64->e_ident[EI_MAG1] != ELFMAG1 || | ||
28 | elf64->e_ident[EI_MAG2] != ELFMAG2 || | ||
29 | elf64->e_ident[EI_MAG3] != ELFMAG3 || | ||
30 | elf64->e_ident[EI_CLASS] != ELFCLASS64 || | ||
31 | elf64->e_ident[EI_DATA] != ELFDATA2MSB || | ||
32 | elf64->e_type != ET_EXEC || elf64->e_machine != EM_PPC64) | ||
33 | return 0; | ||
34 | |||
35 | if ((elf64->e_phoff + sizeof(Elf64_Phdr)) > size) | ||
36 | return 0; | ||
37 | |||
38 | elf64ph = (Elf64_Phdr *) ((unsigned long)elf64 + | ||
39 | (unsigned long)elf64->e_phoff); | ||
40 | |||
41 | r->memsize = (unsigned long)elf64ph->p_memsz; | ||
42 | r->offset = (unsigned long)elf64ph->p_offset; | ||
43 | r->addr = (unsigned long long)elf64ph->p_vaddr; | ||
44 | |||
45 | #ifdef DEBUG | ||
46 | printf("PPC64 ELF file, ph:\n"); | ||
47 | printf("p_type 0x%08x\n", elf64ph->p_type); | ||
48 | printf("p_flags 0x%08x\n", elf64ph->p_flags); | ||
49 | printf("p_offset 0x%016llx\n", elf64ph->p_offset); | ||
50 | printf("p_vaddr 0x%016llx\n", elf64ph->p_vaddr); | ||
51 | printf("p_paddr 0x%016llx\n", elf64ph->p_paddr); | ||
52 | printf("p_filesz 0x%016llx\n", elf64ph->p_filesz); | ||
53 | printf("p_memsz 0x%016llx\n", elf64ph->p_memsz); | ||
54 | printf("p_align 0x%016llx\n", elf64ph->p_align); | ||
55 | printf("... skipping 0x%08lx bytes of ELF header\n", | ||
56 | (unsigned long)elf64ph->p_offset); | ||
57 | #endif | ||
58 | |||
59 | return 64; | ||
60 | } | ||
13 | void get4k(FILE *file, char *buf ) | 61 | void get4k(FILE *file, char *buf ) |
14 | { | 62 | { |
15 | unsigned j; | 63 | unsigned j; |
@@ -34,97 +82,92 @@ void death(const char *msg, FILE *fdesc, const char *fname) | |||
34 | int main(int argc, char **argv) | 82 | int main(int argc, char **argv) |
35 | { | 83 | { |
36 | char inbuf[4096]; | 84 | char inbuf[4096]; |
37 | FILE *ramDisk = NULL; | 85 | struct addr_range vmlinux; |
38 | FILE *sysmap = NULL; | 86 | FILE *ramDisk; |
39 | FILE *inputVmlinux = NULL; | 87 | FILE *inputVmlinux; |
40 | FILE *outputVmlinux = NULL; | 88 | FILE *outputVmlinux; |
41 | 89 | ||
42 | unsigned i = 0; | 90 | char *rd_name, *lx_name, *out_name; |
43 | unsigned long ramFileLen = 0; | 91 | |
44 | unsigned long ramLen = 0; | 92 | size_t i; |
45 | unsigned long roundR = 0; | 93 | unsigned long ramFileLen; |
46 | 94 | unsigned long ramLen; | |
47 | unsigned long sysmapFileLen = 0; | 95 | unsigned long roundR; |
48 | unsigned long sysmapLen = 0; | 96 | unsigned long offset_end; |
49 | unsigned long sysmapPages = 0; | 97 | |
50 | char* ptr_end = NULL; | 98 | unsigned long kernelLen; |
51 | unsigned long offset_end = 0; | 99 | unsigned long actualKernelLen; |
52 | 100 | unsigned long round; | |
53 | unsigned long kernelLen = 0; | 101 | unsigned long roundedKernelLen; |
54 | unsigned long actualKernelLen = 0; | 102 | unsigned long ramStartOffs; |
55 | unsigned long round = 0; | 103 | unsigned long ramPages; |
56 | unsigned long roundedKernelLen = 0; | 104 | unsigned long roundedKernelPages; |
57 | unsigned long ramStartOffs = 0; | 105 | unsigned long hvReleaseData; |
58 | unsigned long ramPages = 0; | ||
59 | unsigned long roundedKernelPages = 0; | ||
60 | unsigned long hvReleaseData = 0; | ||
61 | u_int32_t eyeCatcher = 0xc8a5d9c4; | 106 | u_int32_t eyeCatcher = 0xc8a5d9c4; |
62 | unsigned long naca = 0; | 107 | unsigned long naca; |
63 | unsigned long xRamDisk = 0; | 108 | unsigned long xRamDisk; |
64 | unsigned long xRamDiskSize = 0; | 109 | unsigned long xRamDiskSize; |
65 | long padPages = 0; | 110 | long padPages; |
66 | 111 | ||
67 | 112 | ||
68 | if (argc < 2) { | 113 | if (argc < 2) { |
69 | fprintf(stderr, "Name of RAM disk file missing.\n"); | 114 | fprintf(stderr, "Name of RAM disk file missing.\n"); |
70 | exit(1); | 115 | exit(1); |
71 | } | 116 | } |
117 | rd_name = argv[1]; | ||
72 | 118 | ||
73 | if (argc < 3) { | 119 | if (argc < 3) { |
74 | fprintf(stderr, "Name of System Map input file is missing.\n"); | ||
75 | exit(1); | ||
76 | } | ||
77 | |||
78 | if (argc < 4) { | ||
79 | fprintf(stderr, "Name of vmlinux file missing.\n"); | 120 | fprintf(stderr, "Name of vmlinux file missing.\n"); |
80 | exit(1); | 121 | exit(1); |
81 | } | 122 | } |
123 | lx_name = argv[2]; | ||
82 | 124 | ||
83 | if (argc < 5) { | 125 | if (argc < 4) { |
84 | fprintf(stderr, "Name of vmlinux output file missing.\n"); | 126 | fprintf(stderr, "Name of vmlinux output file missing.\n"); |
85 | exit(1); | 127 | exit(1); |
86 | } | 128 | } |
129 | out_name = argv[3]; | ||
87 | 130 | ||
88 | 131 | ||
89 | ramDisk = fopen(argv[1], "r"); | 132 | ramDisk = fopen(rd_name, "r"); |
90 | if ( ! ramDisk ) { | 133 | if ( ! ramDisk ) { |
91 | fprintf(stderr, "RAM disk file \"%s\" failed to open.\n", argv[1]); | 134 | fprintf(stderr, "RAM disk file \"%s\" failed to open.\n", rd_name); |
92 | exit(1); | 135 | exit(1); |
93 | } | 136 | } |
94 | 137 | ||
95 | sysmap = fopen(argv[2], "r"); | 138 | inputVmlinux = fopen(lx_name, "r"); |
96 | if ( ! sysmap ) { | ||
97 | fprintf(stderr, "System Map file \"%s\" failed to open.\n", argv[2]); | ||
98 | exit(1); | ||
99 | } | ||
100 | |||
101 | inputVmlinux = fopen(argv[3], "r"); | ||
102 | if ( ! inputVmlinux ) { | 139 | if ( ! inputVmlinux ) { |
103 | fprintf(stderr, "vmlinux file \"%s\" failed to open.\n", argv[3]); | 140 | fprintf(stderr, "vmlinux file \"%s\" failed to open.\n", lx_name); |
104 | exit(1); | 141 | exit(1); |
105 | } | 142 | } |
106 | 143 | ||
107 | outputVmlinux = fopen(argv[4], "w+"); | 144 | outputVmlinux = fopen(out_name, "w+"); |
108 | if ( ! outputVmlinux ) { | 145 | if ( ! outputVmlinux ) { |
109 | fprintf(stderr, "output vmlinux file \"%s\" failed to open.\n", argv[4]); | 146 | fprintf(stderr, "output vmlinux file \"%s\" failed to open.\n", out_name); |
110 | exit(1); | 147 | exit(1); |
111 | } | 148 | } |
112 | 149 | ||
113 | 150 | i = fread(inbuf, 1, sizeof(inbuf), inputVmlinux); | |
114 | 151 | if (i != sizeof(inbuf)) { | |
152 | fprintf(stderr, "can not read vmlinux file %s: %u\n", lx_name, i); | ||
153 | exit(1); | ||
154 | } | ||
155 | |||
156 | i = check_elf64(inbuf, sizeof(inbuf), &vmlinux); | ||
157 | if (i == 0) { | ||
158 | fprintf(stderr, "You must have a linux kernel specified as argv[2]\n"); | ||
159 | exit(1); | ||
160 | } | ||
161 | |||
115 | /* Input Vmlinux file */ | 162 | /* Input Vmlinux file */ |
116 | fseek(inputVmlinux, 0, SEEK_END); | 163 | fseek(inputVmlinux, 0, SEEK_END); |
117 | kernelLen = ftell(inputVmlinux); | 164 | kernelLen = ftell(inputVmlinux); |
118 | fseek(inputVmlinux, 0, SEEK_SET); | 165 | fseek(inputVmlinux, 0, SEEK_SET); |
119 | printf("kernel file size = %d\n", kernelLen); | 166 | printf("kernel file size = %lu\n", kernelLen); |
120 | if ( kernelLen == 0 ) { | ||
121 | fprintf(stderr, "You must have a linux kernel specified as argv[3]\n"); | ||
122 | exit(1); | ||
123 | } | ||
124 | 167 | ||
125 | actualKernelLen = kernelLen - ElfHeaderSize; | 168 | actualKernelLen = kernelLen - ElfHeaderSize; |
126 | 169 | ||
127 | printf("actual kernel length (minus ELF header) = %d\n", actualKernelLen); | 170 | printf("actual kernel length (minus ELF header) = %lu\n", actualKernelLen); |
128 | 171 | ||
129 | round = actualKernelLen % 4096; | 172 | round = actualKernelLen % 4096; |
130 | roundedKernelLen = actualKernelLen; | 173 | roundedKernelLen = actualKernelLen; |
@@ -134,39 +177,7 @@ int main(int argc, char **argv) | |||
134 | roundedKernelPages = roundedKernelLen / 4096; | 177 | roundedKernelPages = roundedKernelLen / 4096; |
135 | printf("Vmlinux pages to copy = %ld/0x%lx \n", roundedKernelPages, roundedKernelPages); | 178 | printf("Vmlinux pages to copy = %ld/0x%lx \n", roundedKernelPages, roundedKernelPages); |
136 | 179 | ||
137 | 180 | offset_end = _ALIGN_UP(vmlinux.memsize, 4096); | |
138 | |||
139 | /* Input System Map file */ | ||
140 | /* (needs to be processed simply to determine if we need to add pad pages due to the static variables not being included in the vmlinux) */ | ||
141 | fseek(sysmap, 0, SEEK_END); | ||
142 | sysmapFileLen = ftell(sysmap); | ||
143 | fseek(sysmap, 0, SEEK_SET); | ||
144 | printf("%s file size = %ld/0x%lx \n", argv[2], sysmapFileLen, sysmapFileLen); | ||
145 | |||
146 | sysmapLen = sysmapFileLen; | ||
147 | |||
148 | roundR = 4096 - (sysmapLen % 4096); | ||
149 | if (roundR) { | ||
150 | printf("Rounding System Map file up to a multiple of 4096, adding %ld/0x%lx \n", roundR, roundR); | ||
151 | sysmapLen += roundR; | ||
152 | } | ||
153 | printf("Rounded System Map size is %ld/0x%lx \n", sysmapLen, sysmapLen); | ||
154 | |||
155 | /* Process the Sysmap file to determine where _end is */ | ||
156 | sysmapPages = sysmapLen / 4096; | ||
157 | /* read the whole file line by line, expect that it doesn't fail */ | ||
158 | while ( fgets(inbuf, 4096, sysmap) ) ; | ||
159 | /* search for _end in the last page of the system map */ | ||
160 | ptr_end = strstr(inbuf, " _end"); | ||
161 | if (!ptr_end) { | ||
162 | fprintf(stderr, "Unable to find _end in the sysmap file \n"); | ||
163 | fprintf(stderr, "inbuf: \n"); | ||
164 | fprintf(stderr, "%s \n", inbuf); | ||
165 | exit(1); | ||
166 | } | ||
167 | printf("Found _end in the last page of the sysmap - backing up 10 characters it looks like %s", ptr_end-10); | ||
168 | /* convert address of _end in system map to hex offset. */ | ||
169 | offset_end = (unsigned int)strtol(ptr_end-10, NULL, 16); | ||
170 | /* calc how many pages we need to insert between the vmlinux and the start of the ram disk */ | 181 | /* calc how many pages we need to insert between the vmlinux and the start of the ram disk */ |
171 | padPages = offset_end/4096 - roundedKernelPages; | 182 | padPages = offset_end/4096 - roundedKernelPages; |
172 | 183 | ||
@@ -194,7 +205,7 @@ int main(int argc, char **argv) | |||
194 | fseek(ramDisk, 0, SEEK_END); | 205 | fseek(ramDisk, 0, SEEK_END); |
195 | ramFileLen = ftell(ramDisk); | 206 | ramFileLen = ftell(ramDisk); |
196 | fseek(ramDisk, 0, SEEK_SET); | 207 | fseek(ramDisk, 0, SEEK_SET); |
197 | printf("%s file size = %ld/0x%lx \n", argv[1], ramFileLen, ramFileLen); | 208 | printf("%s file size = %ld/0x%lx \n", rd_name, ramFileLen, ramFileLen); |
198 | 209 | ||
199 | ramLen = ramFileLen; | 210 | ramLen = ramFileLen; |
200 | 211 | ||
@@ -248,19 +259,19 @@ int main(int argc, char **argv) | |||
248 | /* fseek to the hvReleaseData pointer */ | 259 | /* fseek to the hvReleaseData pointer */ |
249 | fseek(outputVmlinux, ElfHeaderSize + 0x24, SEEK_SET); | 260 | fseek(outputVmlinux, ElfHeaderSize + 0x24, SEEK_SET); |
250 | if (fread(&hvReleaseData, 4, 1, outputVmlinux) != 1) { | 261 | if (fread(&hvReleaseData, 4, 1, outputVmlinux) != 1) { |
251 | death("Could not read hvReleaseData pointer\n", outputVmlinux, argv[4]); | 262 | death("Could not read hvReleaseData pointer\n", outputVmlinux, out_name); |
252 | } | 263 | } |
253 | hvReleaseData = ntohl(hvReleaseData); /* Convert to native int */ | 264 | hvReleaseData = ntohl(hvReleaseData); /* Convert to native int */ |
254 | printf("hvReleaseData is at %08x\n", hvReleaseData); | 265 | printf("hvReleaseData is at %08lx\n", hvReleaseData); |
255 | 266 | ||
256 | /* fseek to the hvReleaseData */ | 267 | /* fseek to the hvReleaseData */ |
257 | fseek(outputVmlinux, ElfHeaderSize + hvReleaseData, SEEK_SET); | 268 | fseek(outputVmlinux, ElfHeaderSize + hvReleaseData, SEEK_SET); |
258 | if (fread(inbuf, 0x40, 1, outputVmlinux) != 1) { | 269 | if (fread(inbuf, 0x40, 1, outputVmlinux) != 1) { |
259 | death("Could not read hvReleaseData\n", outputVmlinux, argv[4]); | 270 | death("Could not read hvReleaseData\n", outputVmlinux, out_name); |
260 | } | 271 | } |
261 | /* Check hvReleaseData sanity */ | 272 | /* Check hvReleaseData sanity */ |
262 | if (memcmp(inbuf, &eyeCatcher, 4) != 0) { | 273 | if (memcmp(inbuf, &eyeCatcher, 4) != 0) { |
263 | death("hvReleaseData is invalid\n", outputVmlinux, argv[4]); | 274 | death("hvReleaseData is invalid\n", outputVmlinux, out_name); |
264 | } | 275 | } |
265 | /* Get the naca pointer */ | 276 | /* Get the naca pointer */ |
266 | naca = ntohl(*((u_int32_t*) &inbuf[0x0C])) - KERNELBASE; | 277 | naca = ntohl(*((u_int32_t*) &inbuf[0x0C])) - KERNELBASE; |
@@ -269,13 +280,13 @@ int main(int argc, char **argv) | |||
269 | /* fseek to the naca */ | 280 | /* fseek to the naca */ |
270 | fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET); | 281 | fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET); |
271 | if (fread(inbuf, 0x18, 1, outputVmlinux) != 1) { | 282 | if (fread(inbuf, 0x18, 1, outputVmlinux) != 1) { |
272 | death("Could not read naca\n", outputVmlinux, argv[4]); | 283 | death("Could not read naca\n", outputVmlinux, out_name); |
273 | } | 284 | } |
274 | xRamDisk = ntohl(*((u_int32_t *) &inbuf[0x0c])); | 285 | xRamDisk = ntohl(*((u_int32_t *) &inbuf[0x0c])); |
275 | xRamDiskSize = ntohl(*((u_int32_t *) &inbuf[0x14])); | 286 | xRamDiskSize = ntohl(*((u_int32_t *) &inbuf[0x14])); |
276 | /* Make sure a RAM disk isn't already present */ | 287 | /* Make sure a RAM disk isn't already present */ |
277 | if ((xRamDisk != 0) || (xRamDiskSize != 0)) { | 288 | if ((xRamDisk != 0) || (xRamDiskSize != 0)) { |
278 | death("RAM disk is already attached to this kernel\n", outputVmlinux, argv[4]); | 289 | death("RAM disk is already attached to this kernel\n", outputVmlinux, out_name); |
279 | } | 290 | } |
280 | /* Fill in the values */ | 291 | /* Fill in the values */ |
281 | *((u_int32_t *) &inbuf[0x0c]) = htonl(ramStartOffs); | 292 | *((u_int32_t *) &inbuf[0x0c]) = htonl(ramStartOffs); |
@@ -285,15 +296,15 @@ int main(int argc, char **argv) | |||
285 | fflush(outputVmlinux); | 296 | fflush(outputVmlinux); |
286 | fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET); | 297 | fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET); |
287 | if (fwrite(inbuf, 0x18, 1, outputVmlinux) != 1) { | 298 | if (fwrite(inbuf, 0x18, 1, outputVmlinux) != 1) { |
288 | death("Could not write naca\n", outputVmlinux, argv[4]); | 299 | death("Could not write naca\n", outputVmlinux, out_name); |
289 | } | 300 | } |
290 | printf("Ram Disk of 0x%lx pages is attached to the kernel at offset 0x%08x\n", | 301 | printf("Ram Disk of 0x%lx pages is attached to the kernel at offset 0x%08lx\n", |
291 | ramPages, ramStartOffs); | 302 | ramPages, ramStartOffs); |
292 | 303 | ||
293 | /* Done */ | 304 | /* Done */ |
294 | fclose(outputVmlinux); | 305 | fclose(outputVmlinux); |
295 | /* Set permission to executable */ | 306 | /* Set permission to executable */ |
296 | chmod(argv[4], S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); | 307 | chmod(out_name, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); |
297 | 308 | ||
298 | return 0; | 309 | return 0; |
299 | } | 310 | } |
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile index c441aebe7648..58b19f107656 100644 --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile | |||
@@ -11,12 +11,11 @@ obj-y := misc.o prom.o | |||
11 | 11 | ||
12 | endif | 12 | endif |
13 | 13 | ||
14 | obj-y += irq.o idle.o dma.o \ | 14 | obj-y += idle.o dma.o \ |
15 | align.o pacaData.o \ | 15 | align.o \ |
16 | udbg.o ioctl32.o \ | 16 | udbg.o \ |
17 | rtc.o \ | 17 | rtc.o \ |
18 | cpu_setup_power4.o \ | 18 | iommu.o vdso.o |
19 | iommu.o sysfs.o vdso.o firmware.o | ||
20 | obj-y += vdso32/ vdso64/ | 19 | obj-y += vdso32/ vdso64/ |
21 | 20 | ||
22 | pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o | 21 | pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o |
@@ -31,15 +30,10 @@ endif | |||
31 | obj-$(CONFIG_PPC_PSERIES) += udbg_16550.o | 30 | obj-$(CONFIG_PPC_PSERIES) += udbg_16550.o |
32 | 31 | ||
33 | obj-$(CONFIG_KEXEC) += machine_kexec.o | 32 | obj-$(CONFIG_KEXEC) += machine_kexec.o |
34 | obj-$(CONFIG_EEH) += eeh.o | ||
35 | obj-$(CONFIG_PROC_FS) += proc_ppc64.o | ||
36 | obj-$(CONFIG_MODULES) += module.o | 33 | obj-$(CONFIG_MODULES) += module.o |
37 | ifneq ($(CONFIG_PPC_MERGE),y) | 34 | ifneq ($(CONFIG_PPC_MERGE),y) |
38 | obj-$(CONFIG_MODULES) += ppc_ksyms.o | 35 | obj-$(CONFIG_MODULES) += ppc_ksyms.o |
39 | endif | 36 | endif |
40 | obj-$(CONFIG_PPC_RTAS) += rtas_pci.o | ||
41 | obj-$(CONFIG_SCANLOG) += scanlog.o | ||
42 | obj-$(CONFIG_LPARCFG) += lparcfg.o | ||
43 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o | 37 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o |
44 | ifneq ($(CONFIG_PPC_MERGE),y) | 38 | ifneq ($(CONFIG_PPC_MERGE),y) |
45 | obj-$(CONFIG_BOOTX_TEXT) += btext.o | 39 | obj-$(CONFIG_BOOTX_TEXT) += btext.o |
@@ -52,8 +46,6 @@ obj-$(CONFIG_PPC_MAPLE) += udbg_16550.o | |||
52 | 46 | ||
53 | obj-$(CONFIG_KPROBES) += kprobes.o | 47 | obj-$(CONFIG_KPROBES) += kprobes.o |
54 | 48 | ||
55 | CFLAGS_ioctl32.o += -Ifs/ | ||
56 | |||
57 | ifneq ($(CONFIG_PPC_MERGE),y) | 49 | ifneq ($(CONFIG_PPC_MERGE),y) |
58 | ifeq ($(CONFIG_PPC_ISERIES),y) | 50 | ifeq ($(CONFIG_PPC_ISERIES),y) |
59 | arch/ppc64/kernel/head.o: arch/powerpc/kernel/lparmap.s | 51 | arch/ppc64/kernel/head.o: arch/powerpc/kernel/lparmap.s |
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c index bce9065da6cb..84ab5c18ef52 100644 --- a/arch/ppc64/kernel/asm-offsets.c +++ b/arch/ppc64/kernel/asm-offsets.c | |||
@@ -74,7 +74,6 @@ int main(void) | |||
74 | DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); | 74 | DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); |
75 | DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); | 75 | DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); |
76 | DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); | 76 | DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); |
77 | DEFINE(PLATFORM, offsetof(struct systemcfg, platform)); | ||
78 | DEFINE(PLATFORM_LPAR, PLATFORM_LPAR); | 77 | DEFINE(PLATFORM_LPAR, PLATFORM_LPAR); |
79 | 78 | ||
80 | /* paca */ | 79 | /* paca */ |
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index 9e8050ea1225..1c869ea72d28 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <asm/processor.h> | 28 | #include <asm/processor.h> |
29 | #include <asm/page.h> | 29 | #include <asm/page.h> |
30 | #include <asm/mmu.h> | 30 | #include <asm/mmu.h> |
31 | #include <asm/systemcfg.h> | ||
32 | #include <asm/ppc_asm.h> | 31 | #include <asm/ppc_asm.h> |
33 | #include <asm/asm-offsets.h> | 32 | #include <asm/asm-offsets.h> |
34 | #include <asm/bug.h> | 33 | #include <asm/bug.h> |
@@ -1701,21 +1700,9 @@ _GLOBAL(__secondary_start) | |||
1701 | HMT_MEDIUM /* Set thread priority to MEDIUM */ | 1700 | HMT_MEDIUM /* Set thread priority to MEDIUM */ |
1702 | 1701 | ||
1703 | ld r2,PACATOC(r13) | 1702 | ld r2,PACATOC(r13) |
1704 | li r6,0 | 1703 | |
1705 | stb r6,PACAPROCENABLED(r13) | 1704 | /* Do early setup for that CPU */ |
1706 | 1705 | bl .early_setup_secondary | |
1707 | #ifndef CONFIG_PPC_ISERIES | ||
1708 | /* Initialize the page table pointer register. */ | ||
1709 | LOADADDR(r6,_SDR1) | ||
1710 | ld r6,0(r6) /* get the value of _SDR1 */ | ||
1711 | mtspr SPRN_SDR1,r6 /* set the htab location */ | ||
1712 | #endif | ||
1713 | /* Initialize the first segment table (or SLB) entry */ | ||
1714 | ld r3,PACASTABVIRT(r13) /* get addr of segment table */ | ||
1715 | BEGIN_FTR_SECTION | ||
1716 | bl .stab_initialize | ||
1717 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | ||
1718 | bl .slb_initialize | ||
1719 | 1706 | ||
1720 | /* Initialize the kernel stack. Just a repeat for iSeries. */ | 1707 | /* Initialize the kernel stack. Just a repeat for iSeries. */ |
1721 | LOADADDR(r3,current_set) | 1708 | LOADADDR(r3,current_set) |
@@ -1724,37 +1711,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | |||
1724 | addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD | 1711 | addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD |
1725 | std r1,PACAKSAVE(r13) | 1712 | std r1,PACAKSAVE(r13) |
1726 | 1713 | ||
1727 | ld r3,PACASTABREAL(r13) /* get raddr of segment table */ | ||
1728 | ori r4,r3,1 /* turn on valid bit */ | ||
1729 | |||
1730 | #ifdef CONFIG_PPC_ISERIES | ||
1731 | li r0,-1 /* hypervisor call */ | ||
1732 | li r3,1 | ||
1733 | sldi r3,r3,63 /* 0x8000000000000000 */ | ||
1734 | ori r3,r3,4 /* 0x8000000000000004 */ | ||
1735 | sc /* HvCall_setASR */ | ||
1736 | #else | ||
1737 | /* set the ASR */ | ||
1738 | ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */ | ||
1739 | ld r3,0(r3) | ||
1740 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ | ||
1741 | andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ | ||
1742 | beq 98f /* branch if result is 0 */ | ||
1743 | mfspr r3,SPRN_PVR | ||
1744 | srwi r3,r3,16 | ||
1745 | cmpwi r3,0x37 /* SStar */ | ||
1746 | beq 97f | ||
1747 | cmpwi r3,0x36 /* IStar */ | ||
1748 | beq 97f | ||
1749 | cmpwi r3,0x34 /* Pulsar */ | ||
1750 | bne 98f | ||
1751 | 97: li r3,H_SET_ASR /* hcall = H_SET_ASR */ | ||
1752 | HVSC /* Invoking hcall */ | ||
1753 | b 99f | ||
1754 | 98: /* !(rpa hypervisor) || !(star) */ | ||
1755 | mtasr r4 /* set the stab location */ | ||
1756 | 99: | ||
1757 | #endif | ||
1758 | li r7,0 | 1714 | li r7,0 |
1759 | mtlr r7 | 1715 | mtlr r7 |
1760 | 1716 | ||
@@ -1896,40 +1852,6 @@ _STATIC(start_here_multiplatform) | |||
1896 | mr r3,r31 | 1852 | mr r3,r31 |
1897 | bl .early_setup | 1853 | bl .early_setup |
1898 | 1854 | ||
1899 | /* set the ASR */ | ||
1900 | ld r3,PACASTABREAL(r13) | ||
1901 | ori r4,r3,1 /* turn on valid bit */ | ||
1902 | ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */ | ||
1903 | ld r3,0(r3) | ||
1904 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ | ||
1905 | andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ | ||
1906 | beq 98f /* branch if result is 0 */ | ||
1907 | mfspr r3,SPRN_PVR | ||
1908 | srwi r3,r3,16 | ||
1909 | cmpwi r3,0x37 /* SStar */ | ||
1910 | beq 97f | ||
1911 | cmpwi r3,0x36 /* IStar */ | ||
1912 | beq 97f | ||
1913 | cmpwi r3,0x34 /* Pulsar */ | ||
1914 | bne 98f | ||
1915 | 97: li r3,H_SET_ASR /* hcall = H_SET_ASR */ | ||
1916 | HVSC /* Invoking hcall */ | ||
1917 | b 99f | ||
1918 | 98: /* !(rpa hypervisor) || !(star) */ | ||
1919 | mtasr r4 /* set the stab location */ | ||
1920 | 99: | ||
1921 | /* Set SDR1 (hash table pointer) */ | ||
1922 | ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */ | ||
1923 | ld r3,0(r3) | ||
1924 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ | ||
1925 | /* Test if bit 0 is set (LPAR bit) */ | ||
1926 | andi. r3,r3,PLATFORM_LPAR | ||
1927 | bne 98f /* branch if result is !0 */ | ||
1928 | LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ | ||
1929 | sub r6,r6,r26 | ||
1930 | ld r6,0(r6) /* get the value of _SDR1 */ | ||
1931 | mtspr SPRN_SDR1,r6 /* set the htab location */ | ||
1932 | 98: | ||
1933 | LOADADDR(r3,.start_here_common) | 1855 | LOADADDR(r3,.start_here_common) |
1934 | SET_REG_TO_CONST(r4, MSR_KERNEL) | 1856 | SET_REG_TO_CONST(r4, MSR_KERNEL) |
1935 | mtspr SPRN_SRR0,r3 | 1857 | mtspr SPRN_SRR0,r3 |
diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c index 715bc0e71e0f..b879d3057ef8 100644 --- a/arch/ppc64/kernel/idle.c +++ b/arch/ppc64/kernel/idle.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <asm/processor.h> | 26 | #include <asm/processor.h> |
27 | #include <asm/cputable.h> | 27 | #include <asm/cputable.h> |
28 | #include <asm/time.h> | 28 | #include <asm/time.h> |
29 | #include <asm/systemcfg.h> | ||
30 | #include <asm/machdep.h> | 29 | #include <asm/machdep.h> |
31 | #include <asm/smp.h> | 30 | #include <asm/smp.h> |
32 | 31 | ||
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index 914632ec587d..492bca6137eb 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S | |||
@@ -78,12 +78,12 @@ _GLOBAL(call_do_softirq) | |||
78 | mtlr r0 | 78 | mtlr r0 |
79 | blr | 79 | blr |
80 | 80 | ||
81 | _GLOBAL(call_handle_IRQ_event) | 81 | _GLOBAL(call___do_IRQ) |
82 | mflr r0 | 82 | mflr r0 |
83 | std r0,16(r1) | 83 | std r0,16(r1) |
84 | stdu r1,THREAD_SIZE-112(r6) | 84 | stdu r1,THREAD_SIZE-112(r5) |
85 | mr r1,r6 | 85 | mr r1,r5 |
86 | bl .handle_IRQ_event | 86 | bl .__do_IRQ |
87 | ld r1,0(r1) | 87 | ld r1,0(r1) |
88 | ld r0,16(r1) | 88 | ld r0,16(r1) |
89 | mtlr r0 | 89 | mtlr r0 |
diff --git a/arch/ppc64/kernel/nvram.c b/arch/ppc64/kernel/nvram.c index 4fb1a9f5060d..c0fcd29918ce 100644 --- a/arch/ppc64/kernel/nvram.c +++ b/arch/ppc64/kernel/nvram.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <asm/rtas.h> | 31 | #include <asm/rtas.h> |
32 | #include <asm/prom.h> | 32 | #include <asm/prom.h> |
33 | #include <asm/machdep.h> | 33 | #include <asm/machdep.h> |
34 | #include <asm/systemcfg.h> | ||
35 | 34 | ||
36 | #undef DEBUG_NVRAM | 35 | #undef DEBUG_NVRAM |
37 | 36 | ||
@@ -167,7 +166,7 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file, | |||
167 | case IOC_NVRAM_GET_OFFSET: { | 166 | case IOC_NVRAM_GET_OFFSET: { |
168 | int part, offset; | 167 | int part, offset; |
169 | 168 | ||
170 | if (systemcfg->platform != PLATFORM_POWERMAC) | 169 | if (_machine != PLATFORM_POWERMAC) |
171 | return -EINVAL; | 170 | return -EINVAL; |
172 | if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0) | 171 | if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0) |
173 | return -EFAULT; | 172 | return -EFAULT; |
@@ -450,7 +449,7 @@ static int nvram_setup_partition(void) | |||
450 | * in our nvram, as Apple defined partitions use pretty much | 449 | * in our nvram, as Apple defined partitions use pretty much |
451 | * all of the space | 450 | * all of the space |
452 | */ | 451 | */ |
453 | if (systemcfg->platform == PLATFORM_POWERMAC) | 452 | if (_machine == PLATFORM_POWERMAC) |
454 | return -ENOSPC; | 453 | return -ENOSPC; |
455 | 454 | ||
456 | /* see if we have an OS partition that meets our needs. | 455 | /* see if we have an OS partition that meets our needs. |
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index 30247ff74972..3cef1b8f57f0 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c | |||
@@ -548,6 +548,11 @@ static int __init pcibios_init(void) | |||
548 | if (ppc64_isabridge_dev != NULL) | 548 | if (ppc64_isabridge_dev != NULL) |
549 | printk("ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); | 549 | printk("ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); |
550 | 550 | ||
551 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
552 | /* map in PCI I/O space */ | ||
553 | phbs_remap_io(); | ||
554 | #endif | ||
555 | |||
551 | printk("PCI: Probing PCI hardware done\n"); | 556 | printk("PCI: Probing PCI hardware done\n"); |
552 | 557 | ||
553 | return 0; | 558 | return 0; |
@@ -1277,12 +1282,9 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus, | |||
1277 | * G5 machines... So when something asks for bus 0 io base | 1282 | * G5 machines... So when something asks for bus 0 io base |
1278 | * (bus 0 is HT root), we return the AGP one instead. | 1283 | * (bus 0 is HT root), we return the AGP one instead. |
1279 | */ | 1284 | */ |
1280 | #ifdef CONFIG_PPC_PMAC | 1285 | if (machine_is_compatible("MacRISC4")) |
1281 | if (systemcfg->platform == PLATFORM_POWERMAC && | ||
1282 | machine_is_compatible("MacRISC4")) | ||
1283 | if (in_bus == 0) | 1286 | if (in_bus == 0) |
1284 | in_bus = 0xf0; | 1287 | in_bus = 0xf0; |
1285 | #endif /* CONFIG_PPC_PMAC */ | ||
1286 | 1288 | ||
1287 | /* That syscall isn't quite compatible with PCI domains, but it's | 1289 | /* That syscall isn't quite compatible with PCI domains, but it's |
1288 | * used on pre-domains setup. We return the first match | 1290 | * used on pre-domains setup. We return the first match |
diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c index 1a443a7ada4c..12c4c9e9bbc7 100644 --- a/arch/ppc64/kernel/pci_dn.c +++ b/arch/ppc64/kernel/pci_dn.c | |||
@@ -43,7 +43,7 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data) | |||
43 | u32 *regs; | 43 | u32 *regs; |
44 | struct pci_dn *pdn; | 44 | struct pci_dn *pdn; |
45 | 45 | ||
46 | if (phb->is_dynamic) | 46 | if (mem_init_done) |
47 | pdn = kmalloc(sizeof(*pdn), GFP_KERNEL); | 47 | pdn = kmalloc(sizeof(*pdn), GFP_KERNEL); |
48 | else | 48 | else |
49 | pdn = alloc_bootmem(sizeof(*pdn)); | 49 | pdn = alloc_bootmem(sizeof(*pdn)); |
@@ -120,6 +120,14 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre, | |||
120 | return NULL; | 120 | return NULL; |
121 | } | 121 | } |
122 | 122 | ||
123 | /** | ||
124 | * pci_devs_phb_init_dynamic - setup pci devices under this PHB | ||
125 | * phb: pci-to-host bridge (top-level bridge connecting to cpu) | ||
126 | * | ||
127 | * This routine is called both during boot, (before the memory | ||
128 | * subsystem is set up, before kmalloc is valid) and during the | ||
129 | * dynamic lpar operation of adding a PHB to a running system. | ||
130 | */ | ||
123 | void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb) | 131 | void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb) |
124 | { | 132 | { |
125 | struct device_node * dn = (struct device_node *) phb->arch_data; | 133 | struct device_node * dn = (struct device_node *) phb->arch_data; |
@@ -201,9 +209,14 @@ static struct notifier_block pci_dn_reconfig_nb = { | |||
201 | .notifier_call = pci_dn_reconfig_notifier, | 209 | .notifier_call = pci_dn_reconfig_notifier, |
202 | }; | 210 | }; |
203 | 211 | ||
204 | /* | 212 | /** |
205 | * Actually initialize the phbs. | 213 | * pci_devs_phb_init - Initialize phbs and pci devs under them. |
206 | * The buswalk on this phb has not happened yet. | 214 | * |
215 | * This routine walks over all phb's (pci-host bridges) on the | ||
216 | * system, and sets up assorted pci-related structures | ||
217 | * (including pci info in the device node structs) for each | ||
218 | * pci device found underneath. This routine runs once, | ||
219 | * early in the boot sequence. | ||
207 | */ | 220 | */ |
208 | void __init pci_devs_phb_init(void) | 221 | void __init pci_devs_phb_init(void) |
209 | { | 222 | { |
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index 3402fbee62c7..fbad2c360784 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c | |||
@@ -318,7 +318,7 @@ static int __devinit finish_node_interrupts(struct device_node *np, | |||
318 | } | 318 | } |
319 | 319 | ||
320 | /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ | 320 | /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ |
321 | if (systemcfg->platform == PLATFORM_POWERMAC && ic && ic->parent) { | 321 | if (_machine == PLATFORM_POWERMAC && ic && ic->parent) { |
322 | char *name = get_property(ic->parent, "name", NULL); | 322 | char *name = get_property(ic->parent, "name", NULL); |
323 | if (name && !strcmp(name, "u3")) | 323 | if (name && !strcmp(name, "u3")) |
324 | np->intrs[intrcount].line += 128; | 324 | np->intrs[intrcount].line += 128; |
@@ -1065,7 +1065,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
1065 | prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); | 1065 | prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); |
1066 | if (prop == NULL) | 1066 | if (prop == NULL) |
1067 | return 0; | 1067 | return 0; |
1068 | systemcfg->platform = *prop; | 1068 | _machine = *prop; |
1069 | 1069 | ||
1070 | /* check if iommu is forced on or off */ | 1070 | /* check if iommu is forced on or off */ |
1071 | if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) | 1071 | if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) |
@@ -1230,11 +1230,8 @@ void __init early_init_devtree(void *params) | |||
1230 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); | 1230 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); |
1231 | lmb_enforce_memory_limit(memory_limit); | 1231 | lmb_enforce_memory_limit(memory_limit); |
1232 | lmb_analyze(); | 1232 | lmb_analyze(); |
1233 | systemcfg->physicalMemorySize = lmb_phys_mem_size(); | ||
1234 | lmb_reserve(0, __pa(klimit)); | 1233 | lmb_reserve(0, __pa(klimit)); |
1235 | 1234 | ||
1236 | DBG("Phys. mem: %lx\n", systemcfg->physicalMemorySize); | ||
1237 | |||
1238 | /* Reserve LMB regions used by kernel, initrd, dt, etc... */ | 1235 | /* Reserve LMB regions used by kernel, initrd, dt, etc... */ |
1239 | early_reserve_mem(); | 1236 | early_reserve_mem(); |
1240 | 1237 | ||
@@ -1753,7 +1750,7 @@ static int of_finish_dynamic_node(struct device_node *node, | |||
1753 | /* We don't support that function on PowerMac, at least | 1750 | /* We don't support that function on PowerMac, at least |
1754 | * not yet | 1751 | * not yet |
1755 | */ | 1752 | */ |
1756 | if (systemcfg->platform == PLATFORM_POWERMAC) | 1753 | if (_machine == PLATFORM_POWERMAC) |
1757 | return -ENODEV; | 1754 | return -ENODEV; |
1758 | 1755 | ||
1759 | /* fix up new node's linux_phandle field */ | 1756 | /* fix up new node's linux_phandle field */ |
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index e4c880dab997..6375f40b23db 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c | |||
@@ -1934,7 +1934,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long | |||
1934 | /* | 1934 | /* |
1935 | * On pSeries, inform the firmware about our capabilities | 1935 | * On pSeries, inform the firmware about our capabilities |
1936 | */ | 1936 | */ |
1937 | if (RELOC(of_platform) & PLATFORM_PSERIES) | 1937 | if (RELOC(of_platform) == PLATFORM_PSERIES || |
1938 | RELOC(of_platform) == PLATFORM_PSERIES_LPAR) | ||
1938 | prom_send_capabilities(); | 1939 | prom_send_capabilities(); |
1939 | 1940 | ||
1940 | /* | 1941 | /* |
diff --git a/arch/ppc64/kernel/vdso.c b/arch/ppc64/kernel/vdso.c index 4aacf521e3e4..1bbacac44988 100644 --- a/arch/ppc64/kernel/vdso.c +++ b/arch/ppc64/kernel/vdso.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <asm/machdep.h> | 34 | #include <asm/machdep.h> |
35 | #include <asm/cputable.h> | 35 | #include <asm/cputable.h> |
36 | #include <asm/sections.h> | 36 | #include <asm/sections.h> |
37 | #include <asm/systemcfg.h> | ||
37 | #include <asm/vdso.h> | 38 | #include <asm/vdso.h> |
38 | 39 | ||
39 | #undef DEBUG | 40 | #undef DEBUG |
@@ -179,7 +180,7 @@ static struct page * vdso_vma_nopage(struct vm_area_struct * vma, | |||
179 | * Last page is systemcfg. | 180 | * Last page is systemcfg. |
180 | */ | 181 | */ |
181 | if ((vma->vm_end - address) <= PAGE_SIZE) | 182 | if ((vma->vm_end - address) <= PAGE_SIZE) |
182 | pg = virt_to_page(systemcfg); | 183 | pg = virt_to_page(_systemcfg); |
183 | else | 184 | else |
184 | pg = virt_to_page(vbase + offset); | 185 | pg = virt_to_page(vbase + offset); |
185 | 186 | ||
@@ -604,7 +605,7 @@ void __init vdso_init(void) | |||
604 | get_page(pg); | 605 | get_page(pg); |
605 | } | 606 | } |
606 | 607 | ||
607 | get_page(virt_to_page(systemcfg)); | 608 | get_page(virt_to_page(_systemcfg)); |
608 | } | 609 | } |
609 | 610 | ||
610 | int in_gate_area_no_task(unsigned long addr) | 611 | int in_gate_area_no_task(unsigned long addr) |