aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 06:48:03 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 06:48:03 -0500
commit21af0297c7e56024a5ccc4d8ad2a590f9ec371ba (patch)
tree5d288c1877b1ae9fbe24aa7fabd79565e73d3d2f /arch/mips/kernel
parent5ea293a9048d3a58cb0c840fa719d85ad14cba47 (diff)
parenta9d2517c7a5c8028fbc5296d3af3c75597d3d180 (diff)
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: (68 commits) [MIPS] remove Documentation/mips/GT64120.README [MIPS] Malta: remaining bits of the board support code cleanup [MIPS] Malta: make the helper function static [MIPS] Malta: fix braces at single statement blocks [MIPS] Malta, Atlas: move an extern function declaration to the header file [MIPS] Malta: Use C89 style for comments [MIPS] Malta: else should follow close brace in malta_int.c [MIPS] Malta: remove a superfluous comment [MIPS] Malta: include <linux/cpu.h> instead of <asm/cpu.h> [MIPS] Malta, Atlas, Sead: remove an extern from .c files [MIPS] Malta: fix oversized lines in malta_int.c [MIPS] Malta: remove a dead function declaration [MIPS] Malta: use tabs not spaces [MIPS] Malta: set up the screen info in a separate function [MIPS] Malta: check the PCI clock frequency in a separate function [MIPS] Malta: use the KERN_ facility level in printk() [MIPS] Malta: use Linux kernel style for structure initialization [MIPS]: constify function pointer tables [MIPS] compat: handle argument endianess of sys32_(f)truncate64 with merge_64 [MIPS] Cobalt 64-bits kernels can be safely unmarked experimental ...
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/cpu-bugs64.c47
-rw-r--r--arch/mips/kernel/cpu-probe.c9
-rw-r--r--arch/mips/kernel/genex.S8
-rw-r--r--arch/mips/kernel/kspd.c3
-rw-r--r--arch/mips/kernel/linux32.c30
-rw-r--r--arch/mips/kernel/mips-mt.c1
-rw-r--r--arch/mips/kernel/pcspeaker.c28
-rw-r--r--arch/mips/kernel/proc.c3
-rw-r--r--arch/mips/kernel/rtlx.c1
-rw-r--r--arch/mips/kernel/setup.c7
-rw-r--r--arch/mips/kernel/smp-mt.c193
-rw-r--r--arch/mips/kernel/smp.c53
-rw-r--r--arch/mips/kernel/smtc-proc.c1
-rw-r--r--arch/mips/kernel/smtc.c1
-rw-r--r--arch/mips/kernel/time.c2
-rw-r--r--arch/mips/kernel/vpe.c1
16 files changed, 205 insertions, 183 deletions
diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c
index af78456d4138..417bb3e336ac 100644
--- a/arch/mips/kernel/cpu-bugs64.c
+++ b/arch/mips/kernel/cpu-bugs64.c
@@ -18,6 +18,15 @@
18#include <asm/mipsregs.h> 18#include <asm/mipsregs.h>
19#include <asm/system.h> 19#include <asm/system.h>
20 20
21static char bug64hit[] __initdata =
22 "reliable operation impossible!\n%s";
23static char nowar[] __initdata =
24 "Please report to <linux-mips@linux-mips.org>.";
25static char r4kwar[] __initdata =
26 "Enable CPU_R4000_WORKAROUNDS to rectify.";
27static char daddiwar[] __initdata =
28 "Enable CPU_DADDI_WORKAROUNDS to rectify.";
29
21static inline void align_mod(const int align, const int mod) 30static inline void align_mod(const int align, const int mod)
22{ 31{
23 asm volatile( 32 asm volatile(
@@ -155,13 +164,7 @@ static inline void check_mult_sh(void)
155 } 164 }
156 165
157 printk("no.\n"); 166 printk("no.\n");
158 panic("Reliable operation impossible!\n" 167 panic(bug64hit, !R4000_WAR ? r4kwar : nowar);
159#ifndef CONFIG_CPU_R4000
160 "Configure for R4000 to enable the workaround."
161#else
162 "Please report to <linux-mips@linux-mips.org>."
163#endif
164 );
165} 168}
166 169
167static volatile int daddi_ov __initdata = 0; 170static volatile int daddi_ov __initdata = 0;
@@ -233,15 +236,11 @@ static inline void check_daddi(void)
233 } 236 }
234 237
235 printk("no.\n"); 238 printk("no.\n");
236 panic("Reliable operation impossible!\n" 239 panic(bug64hit, !DADDI_WAR ? daddiwar : nowar);
237#if !defined(CONFIG_CPU_R4000) && !defined(CONFIG_CPU_R4400)
238 "Configure for R4000 or R4400 to enable the workaround."
239#else
240 "Please report to <linux-mips@linux-mips.org>."
241#endif
242 );
243} 240}
244 241
242int daddiu_bug __initdata = -1;
243
245static inline void check_daddiu(void) 244static inline void check_daddiu(void)
246{ 245{
247 long v, w, tmp; 246 long v, w, tmp;
@@ -281,7 +280,9 @@ static inline void check_daddiu(void)
281 : "=&r" (v), "=&r" (w), "=&r" (tmp) 280 : "=&r" (v), "=&r" (w), "=&r" (tmp)
282 : "I" (0xffffffffffffdb9aUL), "I" (0x1234)); 281 : "I" (0xffffffffffffdb9aUL), "I" (0x1234));
283 282
284 if (v == w) { 283 daddiu_bug = v != w;
284
285 if (!daddiu_bug) {
285 printk("no.\n"); 286 printk("no.\n");
286 return; 287 return;
287 } 288 }
@@ -303,18 +304,16 @@ static inline void check_daddiu(void)
303 } 304 }
304 305
305 printk("no.\n"); 306 printk("no.\n");
306 panic("Reliable operation impossible!\n" 307 panic(bug64hit, !DADDI_WAR ? daddiwar : nowar);
307#if !defined(CONFIG_CPU_R4000) && !defined(CONFIG_CPU_R4400)
308 "Configure for R4000 or R4400 to enable the workaround."
309#else
310 "Please report to <linux-mips@linux-mips.org>."
311#endif
312 );
313} 308}
314 309
315void __init check_bugs64(void) 310void __init check_bugs64_early(void)
316{ 311{
317 check_mult_sh(); 312 check_mult_sh();
318 check_daddi();
319 check_daddiu(); 313 check_daddiu();
320} 314}
315
316void __init check_bugs64(void)
317{
318 check_daddi();
319}
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 5c2794391bf5..5861a432a52f 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -188,6 +188,8 @@ static inline void check_wait(void)
188 case CPU_AU1500: 188 case CPU_AU1500:
189 case CPU_AU1550: 189 case CPU_AU1550:
190 case CPU_AU1200: 190 case CPU_AU1200:
191 case CPU_AU1210:
192 case CPU_AU1250:
191 if (allow_au1k_wait) 193 if (allow_au1k_wait)
192 cpu_wait = au1k_wait; 194 cpu_wait = au1k_wait;
193 break; 195 break;
@@ -733,6 +735,11 @@ static inline void cpu_probe_alchemy(struct cpuinfo_mips *c)
733 break; 735 break;
734 case 4: 736 case 4:
735 c->cputype = CPU_AU1200; 737 c->cputype = CPU_AU1200;
738 if (2 == (c->processor_id & 0xff))
739 c->cputype = CPU_AU1250;
740 break;
741 case 5:
742 c->cputype = CPU_AU1210;
736 break; 743 break;
737 default: 744 default:
738 panic("Unknown Au Core!"); 745 panic("Unknown Au Core!");
@@ -858,6 +865,8 @@ static __init const char *cpu_to_name(struct cpuinfo_mips *c)
858 case CPU_AU1100: name = "Au1100"; break; 865 case CPU_AU1100: name = "Au1100"; break;
859 case CPU_AU1550: name = "Au1550"; break; 866 case CPU_AU1550: name = "Au1550"; break;
860 case CPU_AU1200: name = "Au1200"; break; 867 case CPU_AU1200: name = "Au1200"; break;
868 case CPU_AU1210: name = "Au1210"; break;
869 case CPU_AU1250: name = "Au1250"; break;
861 case CPU_4KEC: name = "MIPS 4KEc"; break; 870 case CPU_4KEC: name = "MIPS 4KEc"; break;
862 case CPU_4KSC: name = "MIPS 4KSc"; break; 871 case CPU_4KSC: name = "MIPS 4KSc"; break;
863 case CPU_VR41XX: name = "NEC Vr41xx"; break; 872 case CPU_VR41XX: name = "NEC Vr41xx"; break;
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index e76a76bf0b3d..c6ada98ee042 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -6,7 +6,7 @@
6 * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle 6 * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle
7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8 * Copyright (C) 2001 MIPS Technologies, Inc. 8 * Copyright (C) 2001 MIPS Technologies, Inc.
9 * Copyright (C) 2002 Maciej W. Rozycki 9 * Copyright (C) 2002, 2007 Maciej W. Rozycki
10 */ 10 */
11#include <linux/init.h> 11#include <linux/init.h>
12 12
@@ -471,7 +471,13 @@ NESTED(nmi_handler, PT_SIZE, sp)
471 jr k0 471 jr k0
472 rfe 472 rfe
473#else 473#else
474#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
474 LONG_ADDIU k0, 4 /* stall on $k0 */ 475 LONG_ADDIU k0, 4 /* stall on $k0 */
476#else
477 .set at=v1
478 LONG_ADDIU k0, 4
479 .set noat
480#endif
475 MTC0 k0, CP0_EPC 481 MTC0 k0, CP0_EPC
476 /* I hope three instructions between MTC0 and ERET are enough... */ 482 /* I hope three instructions between MTC0 and ERET are enough... */
477 ori k1, _THREAD_MASK 483 ori k1, _THREAD_MASK
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c
index d2c2e00e5864..f6704ab16306 100644
--- a/arch/mips/kernel/kspd.c
+++ b/arch/mips/kernel/kspd.c
@@ -161,8 +161,7 @@ static unsigned int translate_open_flags(int flags)
161 int i; 161 int i;
162 unsigned int ret = 0; 162 unsigned int ret = 0;
163 163
164 for (i = 0; i < (sizeof(open_flags_table) / sizeof(struct apsp_table)); 164 for (i = 0; i < ARRAY_SIZE(open_flags_table); i++) {
165 i++) {
166 if( (flags & open_flags_table[i].sp) ) { 165 if( (flags & open_flags_table[i].sp) ) {
167 ret |= open_flags_table[i].ap; 166 ret |= open_flags_table[i].ap;
168 } 167 }
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 2b8ec1102e86..65af3cc90abb 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -174,36 +174,16 @@ struct rlimit32 {
174 int rlim_max; 174 int rlim_max;
175}; 175};
176 176
177#ifdef __MIPSEB__ 177asmlinkage long sys32_truncate64(const char __user * path,
178asmlinkage long sys32_truncate64(const char __user * path, unsigned long __dummy, 178 unsigned long __dummy, int a2, int a3)
179 int length_hi, int length_lo)
180#endif
181#ifdef __MIPSEL__
182asmlinkage long sys32_truncate64(const char __user * path, unsigned long __dummy,
183 int length_lo, int length_hi)
184#endif
185{ 179{
186 loff_t length; 180 return sys_truncate(path, merge_64(a2, a3));
187
188 length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo;
189
190 return sys_truncate(path, length);
191} 181}
192 182
193#ifdef __MIPSEB__
194asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy, 183asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy,
195 int length_hi, int length_lo) 184 int a2, int a3)
196#endif
197#ifdef __MIPSEL__
198asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy,
199 int length_lo, int length_hi)
200#endif
201{ 185{
202 loff_t length; 186 return sys_ftruncate(fd, merge_64(a2, a3));
203
204 length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo;
205
206 return sys_ftruncate(fd, length);
207} 187}
208 188
209static inline long 189static inline long
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
index 3d6b1ec1f328..640fb0cc6e39 100644
--- a/arch/mips/kernel/mips-mt.c
+++ b/arch/mips/kernel/mips-mt.c
@@ -17,7 +17,6 @@
17#include <asm/system.h> 17#include <asm/system.h>
18#include <asm/hardirq.h> 18#include <asm/hardirq.h>
19#include <asm/mmu_context.h> 19#include <asm/mmu_context.h>
20#include <asm/smp.h>
21#include <asm/mipsmtregs.h> 20#include <asm/mipsmtregs.h>
22#include <asm/r4kcache.h> 21#include <asm/r4kcache.h>
23#include <asm/cacheflush.h> 22#include <asm/cacheflush.h>
diff --git a/arch/mips/kernel/pcspeaker.c b/arch/mips/kernel/pcspeaker.c
deleted file mode 100644
index 475df6904219..000000000000
--- a/arch/mips/kernel/pcspeaker.c
+++ /dev/null
@@ -1,28 +0,0 @@
1/*
2 * Copyright (C) 2006 IBM Corporation
3 *
4 * Implements device information for i8253 timer chip
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version
8 * 2 as published by the Free Software Foundation
9 */
10
11#include <linux/platform_device.h>
12
13static __init int add_pcspkr(void)
14{
15 struct platform_device *pd;
16 int ret;
17
18 pd = platform_device_alloc("pcspkr", -1);
19 if (!pd)
20 return -ENOMEM;
21
22 ret = platform_device_add(pd);
23 if (ret)
24 platform_device_put(pd);
25
26 return ret;
27}
28device_initcall(add_pcspkr);
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 6e6e947cce1e..36f065398243 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -62,6 +62,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
62 ); 62 );
63 seq_printf(m, "shadow register sets\t: %d\n", 63 seq_printf(m, "shadow register sets\t: %d\n",
64 cpu_data[n].srsets); 64 cpu_data[n].srsets);
65 seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core);
65 66
66 sprintf(fmt, "VCE%%c exceptions\t\t: %s\n", 67 sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
67 cpu_has_vce ? "%u" : "not available"); 68 cpu_has_vce ? "%u" : "not available");
@@ -89,7 +90,7 @@ static void c_stop(struct seq_file *m, void *v)
89{ 90{
90} 91}
91 92
92struct seq_operations cpuinfo_op = { 93const struct seq_operations cpuinfo_op = {
93 .start = c_start, 94 .start = c_start,
94 .next = c_next, 95 .next = c_next,
95 .stop = c_stop, 96 .stop = c_stop,
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 1ba00c15505b..0233798f7155 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -40,7 +40,6 @@
40#include <asm/atomic.h> 40#include <asm/atomic.h>
41#include <asm/cpu.h> 41#include <asm/cpu.h>
42#include <asm/processor.h> 42#include <asm/processor.h>
43#include <asm/mips_mt.h>
44#include <asm/system.h> 43#include <asm/system.h>
45#include <asm/vpe.h> 44#include <asm/vpe.h>
46#include <asm/rtlx.h> 45#include <asm/rtlx.h>
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index f8a535afce39..269c252d956f 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -8,7 +8,7 @@
8 * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02, 03 Ralf Baechle 8 * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02, 03 Ralf Baechle
9 * Copyright (C) 1996 Stoned Elipot 9 * Copyright (C) 1996 Stoned Elipot
10 * Copyright (C) 1999 Silicon Graphics, Inc. 10 * Copyright (C) 1999 Silicon Graphics, Inc.
11 * Copyright (C) 2000 2001, 2002 Maciej W. Rozycki 11 * Copyright (C) 2000, 2001, 2002, 2007 Maciej W. Rozycki
12 */ 12 */
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/ioport.h> 14#include <linux/ioport.h>
@@ -24,10 +24,12 @@
24 24
25#include <asm/addrspace.h> 25#include <asm/addrspace.h>
26#include <asm/bootinfo.h> 26#include <asm/bootinfo.h>
27#include <asm/bugs.h>
27#include <asm/cache.h> 28#include <asm/cache.h>
28#include <asm/cpu.h> 29#include <asm/cpu.h>
29#include <asm/sections.h> 30#include <asm/sections.h>
30#include <asm/setup.h> 31#include <asm/setup.h>
32#include <asm/smp-ops.h>
31#include <asm/system.h> 33#include <asm/system.h>
32 34
33struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly; 35struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly;
@@ -561,6 +563,7 @@ void __init setup_arch(char **cmdline_p)
561 } 563 }
562#endif 564#endif
563 cpu_report(); 565 cpu_report();
566 check_bugs_early();
564 567
565#if defined(CONFIG_VT) 568#if defined(CONFIG_VT)
566#if defined(CONFIG_VGA_CONSOLE) 569#if defined(CONFIG_VGA_CONSOLE)
@@ -573,9 +576,7 @@ void __init setup_arch(char **cmdline_p)
573 arch_mem_init(cmdline_p); 576 arch_mem_init(cmdline_p);
574 577
575 resource_init(); 578 resource_init();
576#ifdef CONFIG_SMP
577 plat_smp_setup(); 579 plat_smp_setup();
578#endif
579} 580}
580 581
581static int __init fpu_disable(char *s) 582static int __init fpu_disable(char *s)
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 94e210cc6cb6..89e6f6aa5166 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -22,6 +22,7 @@
22#include <linux/cpumask.h> 22#include <linux/cpumask.h>
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/compiler.h> 24#include <linux/compiler.h>
25#include <linux/smp.h>
25 26
26#include <asm/atomic.h> 27#include <asm/atomic.h>
27#include <asm/cacheflush.h> 28#include <asm/cacheflush.h>
@@ -30,7 +31,6 @@
30#include <asm/system.h> 31#include <asm/system.h>
31#include <asm/hardirq.h> 32#include <asm/hardirq.h>
32#include <asm/mmu_context.h> 33#include <asm/mmu_context.h>
33#include <asm/smp.h>
34#include <asm/time.h> 34#include <asm/time.h>
35#include <asm/mipsregs.h> 35#include <asm/mipsregs.h>
36#include <asm/mipsmtregs.h> 36#include <asm/mipsmtregs.h>
@@ -215,68 +215,67 @@ static void __init smp_tc_init(unsigned int tc, unsigned int mvpconf0)
215 write_tc_c0_tchalt(TCHALT_H); 215 write_tc_c0_tchalt(TCHALT_H);
216} 216}
217 217
218/* 218static void vsmp_send_ipi_single(int cpu, unsigned int action)
219 * Common setup before any secondaries are started
220 * Make sure all CPU's are in a sensible state before we boot any of the
221 * secondarys
222 */
223void __init plat_smp_setup(void)
224{ 219{
225 unsigned int mvpconf0, ntc, tc, ncpu = 0; 220 int i;
226 221 unsigned long flags;
227#ifdef CONFIG_MIPS_MT_FPAFF 222 int vpflags;
228 /* If we have an FPU, enroll ourselves in the FPU-full mask */
229 if (cpu_has_fpu)
230 cpu_set(0, mt_fpu_cpumask);
231#endif /* CONFIG_MIPS_MT_FPAFF */
232 if (!cpu_has_mipsmt)
233 return;
234
235 /* disable MT so we can configure */
236 dvpe();
237 dmt();
238 223
239 /* Put MVPE's into 'configuration state' */ 224 local_irq_save(flags);
240 set_c0_mvpcontrol(MVPCONTROL_VPC);
241 225
242 mvpconf0 = read_c0_mvpconf0(); 226 vpflags = dvpe(); /* cant access the other CPU's registers whilst MVPE enabled */
243 ntc = (mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT;
244 227
245 /* we'll always have more TC's than VPE's, so loop setting everything 228 switch (action) {
246 to a sensible state */ 229 case SMP_CALL_FUNCTION:
247 for (tc = 0; tc <= ntc; tc++) { 230 i = C_SW1;
248 settc(tc); 231 break;
249 232
250 smp_tc_init(tc, mvpconf0); 233 case SMP_RESCHEDULE_YOURSELF:
251 ncpu = smp_vpe_init(tc, mvpconf0, ncpu); 234 default:
235 i = C_SW0;
236 break;
252 } 237 }
253 238
254 /* Release config state */ 239 /* 1:1 mapping of vpe and tc... */
255 clear_c0_mvpcontrol(MVPCONTROL_VPC); 240 settc(cpu);
241 write_vpe_c0_cause(read_vpe_c0_cause() | i);
242 evpe(vpflags);
256 243
257 /* We'll wait until starting the secondaries before starting MVPE */ 244 local_irq_restore(flags);
245}
258 246
259 printk(KERN_INFO "Detected %i available secondary CPU(s)\n", ncpu); 247static void vsmp_send_ipi_mask(cpumask_t mask, unsigned int action)
248{
249 unsigned int i;
250
251 for_each_cpu_mask(i, mask)
252 vsmp_send_ipi_single(i, action);
260} 253}
261 254
262void __init plat_prepare_cpus(unsigned int max_cpus) 255static void __cpuinit vsmp_init_secondary(void)
263{ 256{
264 mips_mt_set_cpuoptions(); 257 /* Enable per-cpu interrupts */
265 258
266 /* set up ipi interrupts */ 259 /* This is Malta specific: IPI,performance and timer inetrrupts */
267 if (cpu_has_vint) { 260 write_c0_status((read_c0_status() & ~ST0_IM ) |
268 set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch); 261 (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP6 | STATUSF_IP7));
269 set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch); 262}
270 }
271 263
272 cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ; 264static void __cpuinit vsmp_smp_finish(void)
273 cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ; 265{
266 write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ));
274 267
275 setup_irq(cpu_ipi_resched_irq, &irq_resched); 268#ifdef CONFIG_MIPS_MT_FPAFF
276 setup_irq(cpu_ipi_call_irq, &irq_call); 269 /* If we have an FPU, enroll ourselves in the FPU-full mask */
270 if (cpu_has_fpu)
271 cpu_set(smp_processor_id(), mt_fpu_cpumask);
272#endif /* CONFIG_MIPS_MT_FPAFF */
277 273
278 set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq); 274 local_irq_enable();
279 set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq); 275}
276
277static void vsmp_cpus_done(void)
278{
280} 279}
281 280
282/* 281/*
@@ -287,7 +286,7 @@ void __init plat_prepare_cpus(unsigned int max_cpus)
287 * (unsigned long)idle->thread_info the gp 286 * (unsigned long)idle->thread_info the gp
288 * assumes a 1:1 mapping of TC => VPE 287 * assumes a 1:1 mapping of TC => VPE
289 */ 288 */
290void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) 289static void __cpuinit vsmp_boot_secondary(int cpu, struct task_struct *idle)
291{ 290{
292 struct thread_info *gp = task_thread_info(idle); 291 struct thread_info *gp = task_thread_info(idle);
293 dvpe(); 292 dvpe();
@@ -321,57 +320,81 @@ void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle)
321 evpe(EVPE_ENABLE); 320 evpe(EVPE_ENABLE);
322} 321}
323 322
324void __cpuinit prom_init_secondary(void) 323/*
325{ 324 * Common setup before any secondaries are started
326 /* Enable per-cpu interrupts */ 325 * Make sure all CPU's are in a sensible state before we boot any of the
327 326 * secondarys
328 /* This is Malta specific: IPI,performance and timer inetrrupts */ 327 */
329 write_c0_status((read_c0_status() & ~ST0_IM ) | 328static void __init vsmp_smp_setup(void)
330 (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP6 | STATUSF_IP7));
331}
332
333void __cpuinit prom_smp_finish(void)
334{ 329{
335 write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ)); 330 unsigned int mvpconf0, ntc, tc, ncpu = 0;
331 unsigned int nvpe;
336 332
337#ifdef CONFIG_MIPS_MT_FPAFF 333#ifdef CONFIG_MIPS_MT_FPAFF
338 /* If we have an FPU, enroll ourselves in the FPU-full mask */ 334 /* If we have an FPU, enroll ourselves in the FPU-full mask */
339 if (cpu_has_fpu) 335 if (cpu_has_fpu)
340 cpu_set(smp_processor_id(), mt_fpu_cpumask); 336 cpu_set(0, mt_fpu_cpumask);
341#endif /* CONFIG_MIPS_MT_FPAFF */ 337#endif /* CONFIG_MIPS_MT_FPAFF */
338 if (!cpu_has_mipsmt)
339 return;
342 340
343 local_irq_enable(); 341 /* disable MT so we can configure */
344} 342 dvpe();
343 dmt();
345 344
346void prom_cpus_done(void) 345 /* Put MVPE's into 'configuration state' */
347{ 346 set_c0_mvpcontrol(MVPCONTROL_VPC);
348}
349 347
350void core_send_ipi(int cpu, unsigned int action) 348 mvpconf0 = read_c0_mvpconf0();
351{ 349 ntc = (mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT;
352 int i;
353 unsigned long flags;
354 int vpflags;
355 350
356 local_irq_save(flags); 351 nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
352 smp_num_siblings = nvpe;
357 353
358 vpflags = dvpe(); /* cant access the other CPU's registers whilst MVPE enabled */ 354 /* we'll always have more TC's than VPE's, so loop setting everything
355 to a sensible state */
356 for (tc = 0; tc <= ntc; tc++) {
357 settc(tc);
359 358
360 switch (action) { 359 smp_tc_init(tc, mvpconf0);
361 case SMP_CALL_FUNCTION: 360 ncpu = smp_vpe_init(tc, mvpconf0, ncpu);
362 i = C_SW1; 361 }
363 break;
364 362
365 case SMP_RESCHEDULE_YOURSELF: 363 /* Release config state */
366 default: 364 clear_c0_mvpcontrol(MVPCONTROL_VPC);
367 i = C_SW0; 365
368 break; 366 /* We'll wait until starting the secondaries before starting MVPE */
367
368 printk(KERN_INFO "Detected %i available secondary CPU(s)\n", ncpu);
369}
370
371static void __init vsmp_prepare_cpus(unsigned int max_cpus)
372{
373 mips_mt_set_cpuoptions();
374
375 /* set up ipi interrupts */
376 if (cpu_has_vint) {
377 set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
378 set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
369 } 379 }
370 380
371 /* 1:1 mapping of vpe and tc... */ 381 cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
372 settc(cpu); 382 cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ;
373 write_vpe_c0_cause(read_vpe_c0_cause() | i);
374 evpe(vpflags);
375 383
376 local_irq_restore(flags); 384 setup_irq(cpu_ipi_resched_irq, &irq_resched);
385 setup_irq(cpu_ipi_call_irq, &irq_call);
386
387 set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq);
388 set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq);
377} 389}
390
391struct plat_smp_ops vsmp_smp_ops = {
392 .send_ipi_single = vsmp_send_ipi_single,
393 .send_ipi_mask = vsmp_send_ipi_mask,
394 .init_secondary = vsmp_init_secondary,
395 .smp_finish = vsmp_smp_finish,
396 .cpus_done = vsmp_cpus_done,
397 .boot_secondary = vsmp_boot_secondary,
398 .smp_setup = vsmp_smp_setup,
399 .prepare_cpus = vsmp_prepare_cpus,
400};
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 63989e9df4f9..1e5dfc28294a 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -37,7 +37,6 @@
37#include <asm/processor.h> 37#include <asm/processor.h>
38#include <asm/system.h> 38#include <asm/system.h>
39#include <asm/mmu_context.h> 39#include <asm/mmu_context.h>
40#include <asm/smp.h>
41#include <asm/time.h> 40#include <asm/time.h>
42 41
43#ifdef CONFIG_MIPS_MT_SMTC 42#ifdef CONFIG_MIPS_MT_SMTC
@@ -56,6 +55,44 @@ EXPORT_SYMBOL(cpu_online_map);
56extern void __init calibrate_delay(void); 55extern void __init calibrate_delay(void);
57extern void cpu_idle(void); 56extern void cpu_idle(void);
58 57
58/* Number of TCs (or siblings in Intel speak) per CPU core */
59int smp_num_siblings = 1;
60EXPORT_SYMBOL(smp_num_siblings);
61
62/* representing the TCs (or siblings in Intel speak) of each logical CPU */
63cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
64EXPORT_SYMBOL(cpu_sibling_map);
65
66/* representing cpus for which sibling maps can be computed */
67static cpumask_t cpu_sibling_setup_map;
68
69static inline void set_cpu_sibling_map(int cpu)
70{
71 int i;
72
73 cpu_set(cpu, cpu_sibling_setup_map);
74
75 if (smp_num_siblings > 1) {
76 for_each_cpu_mask(i, cpu_sibling_setup_map) {
77 if (cpu_data[cpu].core == cpu_data[i].core) {
78 cpu_set(i, cpu_sibling_map[cpu]);
79 cpu_set(cpu, cpu_sibling_map[i]);
80 }
81 }
82 } else
83 cpu_set(cpu, cpu_sibling_map[cpu]);
84}
85
86struct plat_smp_ops *mp_ops;
87
88__cpuinit void register_smp_ops(struct plat_smp_ops *ops)
89{
90 if (ops)
91 printk(KERN_WARNING "Overriding previous set SMP ops\n");
92
93 mp_ops = ops;
94}
95
59/* 96/*
60 * First C code run on the secondary CPUs after being started up by 97 * First C code run on the secondary CPUs after being started up by
61 * the master. 98 * the master.
@@ -72,7 +109,7 @@ asmlinkage __cpuinit void start_secondary(void)
72 cpu_report(); 109 cpu_report();
73 per_cpu_trap_init(); 110 per_cpu_trap_init();
74 mips_clockevent_init(); 111 mips_clockevent_init();
75 prom_init_secondary(); 112 mp_ops->init_secondary();
76 113
77 /* 114 /*
78 * XXX parity protection should be folded in here when it's converted 115 * XXX parity protection should be folded in here when it's converted
@@ -84,7 +121,8 @@ asmlinkage __cpuinit void start_secondary(void)
84 cpu = smp_processor_id(); 121 cpu = smp_processor_id();
85 cpu_data[cpu].udelay_val = loops_per_jiffy; 122 cpu_data[cpu].udelay_val = loops_per_jiffy;
86 123
87 prom_smp_finish(); 124 mp_ops->smp_finish();
125 set_cpu_sibling_map(cpu);
88 126
89 cpu_set(cpu, cpu_callin_map); 127 cpu_set(cpu, cpu_callin_map);
90 128
@@ -155,7 +193,7 @@ int smp_call_function_mask(cpumask_t mask, void (*func) (void *info),
155 smp_mb(); 193 smp_mb();
156 194
157 /* Send a message to all other CPUs and wait for them to respond */ 195 /* Send a message to all other CPUs and wait for them to respond */
158 core_send_ipi_mask(mask, SMP_CALL_FUNCTION); 196 mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION);
159 197
160 /* Wait for response */ 198 /* Wait for response */
161 /* FIXME: lock-up detection, backtrace on lock-up */ 199 /* FIXME: lock-up detection, backtrace on lock-up */
@@ -249,7 +287,7 @@ void smp_send_stop(void)
249 287
250void __init smp_cpus_done(unsigned int max_cpus) 288void __init smp_cpus_done(unsigned int max_cpus)
251{ 289{
252 prom_cpus_done(); 290 mp_ops->cpus_done();
253} 291}
254 292
255/* called from main before smp_init() */ 293/* called from main before smp_init() */
@@ -257,7 +295,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
257{ 295{
258 init_new_context(current, &init_mm); 296 init_new_context(current, &init_mm);
259 current_thread_info()->cpu = 0; 297 current_thread_info()->cpu = 0;
260 plat_prepare_cpus(max_cpus); 298 mp_ops->prepare_cpus(max_cpus);
299 set_cpu_sibling_map(0);
261#ifndef CONFIG_HOTPLUG_CPU 300#ifndef CONFIG_HOTPLUG_CPU
262 cpu_present_map = cpu_possible_map; 301 cpu_present_map = cpu_possible_map;
263#endif 302#endif
@@ -295,7 +334,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
295 if (IS_ERR(idle)) 334 if (IS_ERR(idle))
296 panic(KERN_ERR "Fork failed for CPU %d", cpu); 335 panic(KERN_ERR "Fork failed for CPU %d", cpu);
297 336
298 prom_boot_secondary(cpu, idle); 337 mp_ops->boot_secondary(cpu, idle);
299 338
300 /* 339 /*
301 * Trust is futile. We should really have timeouts ... 340 * Trust is futile. We should really have timeouts ...
diff --git a/arch/mips/kernel/smtc-proc.c b/arch/mips/kernel/smtc-proc.c
index 6f3709996172..fe256559c997 100644
--- a/arch/mips/kernel/smtc-proc.c
+++ b/arch/mips/kernel/smtc-proc.c
@@ -14,7 +14,6 @@
14#include <asm/system.h> 14#include <asm/system.h>
15#include <asm/hardirq.h> 15#include <asm/hardirq.h>
16#include <asm/mmu_context.h> 16#include <asm/mmu_context.h>
17#include <asm/smp.h>
18#include <asm/mipsregs.h> 17#include <asm/mipsregs.h>
19#include <asm/cacheflush.h> 18#include <asm/cacheflush.h>
20#include <linux/proc_fs.h> 19#include <linux/proc_fs.h>
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index 9c92d42996cb..85f700e58131 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -16,7 +16,6 @@
16#include <asm/hazards.h> 16#include <asm/hazards.h>
17#include <asm/irq.h> 17#include <asm/irq.h>
18#include <asm/mmu_context.h> 18#include <asm/mmu_context.h>
19#include <asm/smp.h>
20#include <asm/mipsregs.h> 19#include <asm/mipsregs.h>
21#include <asm/cacheflush.h> 20#include <asm/cacheflush.h>
22#include <asm/time.h> 21#include <asm/time.h>
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 2995be1ab3ca..9f85d4cecc5b 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -50,8 +50,6 @@ int update_persistent_clock(struct timespec now)
50 return rtc_mips_set_mmss(now.tv_sec); 50 return rtc_mips_set_mmss(now.tv_sec);
51} 51}
52 52
53int (*mips_timer_state)(void);
54
55int null_perf_irq(void) 53int null_perf_irq(void)
56{ 54{
57 return 0; 55 return 0;
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index c06eb812a95e..eed2dc4273e0 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -53,7 +53,6 @@
53#include <asm/system.h> 53#include <asm/system.h>
54#include <asm/vpe.h> 54#include <asm/vpe.h>
55#include <asm/kspd.h> 55#include <asm/kspd.h>
56#include <asm/mips_mt.h>
57 56
58typedef void *vpe_handle; 57typedef void *vpe_handle;
59 58