From 0ca5921e791fb2011d4d6de787f6485b3900703d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 19 Jun 2009 13:51:28 +0100 Subject: MIPS: bug.h Build fix - include . In the past this file somehow used to be dragged in. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/bug.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/mips/include/asm/bug.h b/arch/mips/include/asm/bug.h index 08ea46863fe..6cf29c26e87 100644 --- a/arch/mips/include/asm/bug.h +++ b/arch/mips/include/asm/bug.h @@ -1,6 +1,7 @@ #ifndef __ASM_BUG_H #define __ASM_BUG_H +#include #include #ifdef CONFIG_BUG -- cgit v1.2.3-70-g09d2 From 631330f5847b3f8a7ea67d689e9f7c56833ccaa6 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 19 Jun 2009 14:05:26 +0100 Subject: MIPS: Build fix - include into all smp_processor_id() users. Some of the were relying into smp.h being dragged in by another header which of course is fragile. uses smp_processor_id() only in macros and including smp.h there leads to an include loop, so don't change cpu-info.h. Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/octeon-irq.c | 2 +- arch/mips/cavium-octeon/setup.c | 1 + arch/mips/include/asm/bugs.h | 1 + arch/mips/include/asm/irq.h | 1 + arch/mips/include/asm/mmu_context.h | 1 + arch/mips/include/asm/smp.h | 1 + arch/mips/include/asm/sn/addrs.h | 1 + arch/mips/jazz/irq.c | 1 + arch/mips/kernel/cevt-bcm1480.c | 1 + arch/mips/kernel/cevt-r4k.c | 1 + arch/mips/kernel/cevt-sb1250.c | 1 + arch/mips/kernel/cevt-smtc.c | 1 + arch/mips/kernel/cpu-probe.c | 1 + arch/mips/kernel/i8253.c | 1 + arch/mips/kernel/irq-gic.c | 1 + arch/mips/kernel/kgdb.c | 1 + arch/mips/kernel/smp-cmp.c | 1 + arch/mips/kernel/smp.c | 1 + arch/mips/kernel/smtc.c | 1 + arch/mips/mm/c-octeon.c | 1 + arch/mips/mm/c-r3k.c | 1 + arch/mips/mm/c-r4k.c | 1 + arch/mips/mm/c-tx39.c | 1 + arch/mips/mm/highmem.c | 1 + arch/mips/mm/init.c | 1 + arch/mips/mm/page.c | 1 + arch/mips/mm/tlb-r3k.c | 1 + arch/mips/mm/tlb-r4k.c | 1 + arch/mips/mm/tlb-r8k.c | 1 + arch/mips/mm/tlbex.c | 1 + arch/mips/mti-malta/malta-int.c | 1 + arch/mips/pci/pci-ip27.c | 1 + arch/mips/pmc-sierra/yosemite/smp.c | 1 + arch/mips/sgi-ip27/ip27-init.c | 1 + arch/mips/sgi-ip27/ip27-irq.c | 1 + arch/mips/sgi-ip27/ip27-timer.c | 1 + arch/mips/sgi-ip27/ip27-xtalk.c | 1 + arch/mips/sibyte/bcm1480/irq.c | 1 + arch/mips/sni/time.c | 1 + 39 files changed, 39 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 8dfa009e007..3090ee37e10 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -7,7 +7,7 @@ */ #include #include -#include +#include #include #include diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 5f4e49ba471..da559249cc2 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include /* for memset */ #include diff --git a/arch/mips/include/asm/bugs.h b/arch/mips/include/asm/bugs.h index 9dc10df3207..b160a706795 100644 --- a/arch/mips/include/asm/bugs.h +++ b/arch/mips/include/asm/bugs.h @@ -11,6 +11,7 @@ #include #include +#include #include #include diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h index 4f1eed107b0..09b08d05ff7 100644 --- a/arch/mips/include/asm/irq.h +++ b/arch/mips/include/asm/irq.h @@ -10,6 +10,7 @@ #define _ASM_IRQ_H #include +#include #include diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h index d7f3eb03ad1..d3bea88d874 100644 --- a/arch/mips/include/asm/mmu_context.h +++ b/arch/mips/include/asm/mmu_context.h @@ -13,6 +13,7 @@ #include #include +#include #include #include #include diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h index 40e5ef1d4d2..2f83fa8631d 100644 --- a/arch/mips/include/asm/smp.h +++ b/arch/mips/include/asm/smp.h @@ -13,6 +13,7 @@ #include #include +#include #include #include diff --git a/arch/mips/include/asm/sn/addrs.h b/arch/mips/include/asm/sn/addrs.h index 3a56d90abfa..2367b56dcde 100644 --- a/arch/mips/include/asm/sn/addrs.h +++ b/arch/mips/include/asm/sn/addrs.h @@ -11,6 +11,7 @@ #ifndef __ASSEMBLY__ +#include #include #endif /* !__ASSEMBLY__ */ diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c index d9b6a5b5399..7fd170d007e 100644 --- a/arch/mips/jazz/irq.c +++ b/arch/mips/jazz/irq.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include diff --git a/arch/mips/kernel/cevt-bcm1480.c b/arch/mips/kernel/cevt-bcm1480.c index a5182a20769..e02f79b1eb5 100644 --- a/arch/mips/kernel/cevt-bcm1480.c +++ b/arch/mips/kernel/cevt-bcm1480.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 0015e442572..2652362ce04 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include diff --git a/arch/mips/kernel/cevt-sb1250.c b/arch/mips/kernel/cevt-sb1250.c index 340f53e5c6b..ac5903d1b20 100644 --- a/arch/mips/kernel/cevt-sb1250.c +++ b/arch/mips/kernel/cevt-sb1250.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include diff --git a/arch/mips/kernel/cevt-smtc.c b/arch/mips/kernel/cevt-smtc.c index df6f5bc6057..98bd7de7577 100644 --- a/arch/mips/kernel/cevt-smtc.c +++ b/arch/mips/kernel/cevt-smtc.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index b13b8eb3059..1abe9905c9c 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c index ed20e7fe65e..f7d8d5d0ddb 100644 --- a/arch/mips/kernel/i8253.c +++ b/arch/mips/kernel/i8253.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c index 3f43c2e3aa5..39000f103f2 100644 --- a/arch/mips/kernel/irq-gic.c +++ b/arch/mips/kernel/irq-gic.c @@ -2,6 +2,7 @@ #include #include +#include #include #include diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c index 6e152c80cd4..50c9bb88066 100644 --- a/arch/mips/kernel/kgdb.c +++ b/arch/mips/kernel/kgdb.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c index f27beca4b26..653be061b9e 100644 --- a/arch/mips/kernel/smp-cmp.c +++ b/arch/mips/kernel/smp-cmp.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index c937506a03a..58f4679bbd4 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 37d51cd124e..8a0626cbb10 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c index 44d01a0a849..b165cdcb281 100644 --- a/arch/mips/mm/c-octeon.c +++ b/arch/mips/mm/c-octeon.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c index 5500c20c79a..54e5f7b9f44 100644 --- a/arch/mips/mm/c-r3k.c +++ b/arch/mips/mm/c-r3k.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 71fe4cb778c..6721ee2b1e8 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c index f7c8f9ce39c..6515b441871 100644 --- a/arch/mips/mm/c-tx39.c +++ b/arch/mips/mm/c-tx39.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c index 2b1309b2580..e274fda329f 100644 --- a/arch/mips/mm/highmem.c +++ b/arch/mips/mm/highmem.c @@ -1,5 +1,6 @@ #include #include +#include #include #include diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index c5511294a9e..0e820508ff2 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c index 48060c635ac..f5c73754d66 100644 --- a/arch/mips/mm/page.c +++ b/arch/mips/mm/page.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c index 1c0048a6f5c..0f5ab236ab6 100644 --- a/arch/mips/mm/tlb-r3k.c +++ b/arch/mips/mm/tlb-r3k.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index f60fe513eb6..cee502caf39 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -10,6 +10,7 @@ */ #include #include +#include #include #include diff --git a/arch/mips/mm/tlb-r8k.c b/arch/mips/mm/tlb-r8k.c index 4ec95cc2df2..2b82f23df1a 100644 --- a/arch/mips/mm/tlb-r8k.c +++ b/arch/mips/mm/tlb-r8k.c @@ -10,6 +10,7 @@ */ #include #include +#include #include #include diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 8f606ead826..9a17bf8395d 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index ea176113fea..b4eaf137e4a 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index dda6f205866..a0e726eb039 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c index f78c29b68d7..8ace2771623 100644 --- a/arch/mips/pmc-sierra/yosemite/smp.c +++ b/arch/mips/pmc-sierra/yosemite/smp.c @@ -1,5 +1,6 @@ #include #include +#include #include #include diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index 4a500e8cd3c..51d3a4f2d7e 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 1bb692a3b31..c1c8e40d65d 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index f10a7cd64f7..6d0e59ffba2 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/sgi-ip27/ip27-xtalk.c b/arch/mips/sgi-ip27/ip27-xtalk.c index 6ae64e8dfc4..5e871e75a8d 100644 --- a/arch/mips/sgi-ip27/ip27-xtalk.c +++ b/arch/mips/sgi-ip27/ip27-xtalk.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c index 690de06bde9..ba59839a021 100644 --- a/arch/mips/sibyte/bcm1480/irq.c +++ b/arch/mips/sibyte/bcm1480/irq.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c index 69f5f88711c..0d9ec1a5c24 100644 --- a/arch/mips/sni/time.c +++ b/arch/mips/sni/time.c @@ -1,5 +1,6 @@ #include #include +#include #include #include -- cgit v1.2.3-70-g09d2 From 44eeab67416711db9b84610ef18c99a60415dff8 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 19 Jun 2009 15:01:44 +0100 Subject: MIPS: Hibernation: Remove SMP TLB and cacheflushing code. We can't perform any flushes on SMP from swsusp_arch_resume because interrupts are disabled. A cross-CPU flush is unnecessary anyway because all but the local CPU have already been disabled. A local flush is not needed either because we didn't change any mappings. So just delete the code. Signed-off-by: Ralf Baechle --- arch/mips/power/hibernate.S | 9 --------- 1 file changed, 9 deletions(-) (limited to 'arch') diff --git a/arch/mips/power/hibernate.S b/arch/mips/power/hibernate.S index 486bd3fd01a..4b8174b382d 100644 --- a/arch/mips/power/hibernate.S +++ b/arch/mips/power/hibernate.S @@ -43,15 +43,6 @@ LEAF(swsusp_arch_resume) bne t1, t3, 1b PTR_L t0, PBE_NEXT(t0) bnez t0, 0b - /* flush caches to make sure context is in memory */ - PTR_L t0, __flush_cache_all - jalr t0 - /* flush tlb entries */ -#ifdef CONFIG_SMP - jal flush_tlb_all -#else - jal local_flush_tlb_all -#endif PTR_LA t0, saved_regs PTR_L ra, PT_R31(t0) PTR_L sp, PT_R29(t0) -- cgit v1.2.3-70-g09d2 From ab7f6f3010a6c5ae147541168705a446cee511e7 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 22 Jun 2009 15:48:27 +0100 Subject: MIPS: MIPSsim: Fix build error if MSC01E_INT_BASE is undefined. This fixes kernel.org bugzilla 13595, see http://bugzilla.kernel.org/show_bug.cgi?id=13595 Reported-by: dvice_null@yahoo.com Signed-off-by: Ralf Baechle --- arch/mips/mipssim/sim_time.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/mips/mipssim/sim_time.c b/arch/mips/mipssim/sim_time.c index 881ecbc1fa2..0cea932f124 100644 --- a/arch/mips/mipssim/sim_time.c +++ b/arch/mips/mipssim/sim_time.c @@ -91,6 +91,7 @@ unsigned __cpuinit get_c0_compare_int(void) mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR; } else { #endif + { if (cpu_has_vint) set_vi_handler(cp0_compare_irq, mips_timer_dispatch); mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; -- cgit v1.2.3-70-g09d2 From 2e25406fb878e2313a9d8e302ed7ff3c2831198f Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 22 Jun 2009 16:17:52 +0100 Subject: MIPS: Sibyte: Fix build error if CONFIG_SERIAL_SB1250_DUART is undefined. This fixes kernel.org bugzilla 13596, see http://bugzilla.kernel.org/show_bug.cgi?id=13596 Reported-by: dvice_null@yahoo.com Signed-off-by: Ralf Baechle --- arch/mips/sibyte/common/cfe_console.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/sibyte/common/cfe_console.c b/arch/mips/sibyte/common/cfe_console.c index 81e3d54376e..1ad2da103fe 100644 --- a/arch/mips/sibyte/common/cfe_console.c +++ b/arch/mips/sibyte/common/cfe_console.c @@ -51,12 +51,13 @@ static int cfe_console_setup(struct console *cons, char *str) setleds("u0cn"); } else if (!strcmp(consdev, "uart1")) { setleds("u1cn"); + } else #endif #ifdef CONFIG_VGA_CONSOLE - } else if (!strcmp(consdev, "pcconsole0")) { - setleds("pccn"); -#endif + if (!strcmp(consdev, "pcconsole0")) { + setleds("pccn"); } else +#endif return -ENODEV; } return 0; -- cgit v1.2.3-70-g09d2 From 1b2bc75c1bde6581d2694cb3ed7fb06b69685008 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 23 Jun 2009 10:00:31 +0100 Subject: MIPS: Add arch generic CPU hotplug Each platform has to add support for CPU hotplugging itself by providing suitable definitions for the cpu_disable and cpu_die of the smp_ops methods and setting SYS_SUPPORTS_HOTPLUG_CPU. A platform should only set SYS_SUPPORTS_HOTPLUG_CPU once all it's smp_ops definitions have the necessary changes. This patch contains the changes to the dummy smp_ops definition for uni-processor systems. Parts of the code contributed by Cavium Inc. Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 11 ++++++++++- arch/mips/include/asm/smp-ops.h | 4 ++++ arch/mips/include/asm/smp.h | 19 +++++++++++++++++++ arch/mips/kernel/process.c | 13 ++++++++++++- arch/mips/kernel/smp-up.c | 16 ++++++++++++++++ arch/mips/kernel/smp.c | 17 +++++++++++++---- arch/mips/kernel/topology.c | 5 ++++- 7 files changed, 78 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index b29f0280d71..eb7e8d795c6 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -784,8 +784,17 @@ config SYS_HAS_EARLY_PRINTK bool config HOTPLUG_CPU + bool "Support for hot-pluggable CPUs" + depends on SMP && HOTPLUG && SYS_SUPPORTS_HOTPLUG_CPU + help + Say Y here to allow turning CPUs off and on. CPUs can be + controlled through /sys/devices/system/cpu. + (Note: power management support will enable this option + automatically on SMP systems. ) + Say N if you want to disable CPU hotplug. + +config SYS_SUPPORTS_HOTPLUG_CPU bool - default n config I8259 bool diff --git a/arch/mips/include/asm/smp-ops.h b/arch/mips/include/asm/smp-ops.h index 64ffc0290b8..fd545547b8a 100644 --- a/arch/mips/include/asm/smp-ops.h +++ b/arch/mips/include/asm/smp-ops.h @@ -26,6 +26,10 @@ struct plat_smp_ops { void (*boot_secondary)(int cpu, struct task_struct *idle); void (*smp_setup)(void); void (*prepare_cpus)(unsigned int max_cpus); +#ifdef CONFIG_HOTPLUG_CPU + int (*cpu_disable)(void); + void (*cpu_die)(unsigned int cpu); +#endif }; extern void register_smp_ops(struct plat_smp_ops *ops); diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h index 2f83fa8631d..01f813dc388 100644 --- a/arch/mips/include/asm/smp.h +++ b/arch/mips/include/asm/smp.h @@ -41,6 +41,7 @@ extern int __cpu_logical_map[NR_CPUS]; /* Octeon - Tell another core to flush its icache */ #define SMP_ICACHE_FLUSH 0x4 +extern cpumask_t cpu_callin_map; extern void asmlinkage smp_bootstrap(void); @@ -56,6 +57,24 @@ static inline void smp_send_reschedule(int cpu) mp_ops->send_ipi_single(cpu, SMP_RESCHEDULE_YOURSELF); } +#ifdef CONFIG_HOTPLUG_CPU +static inline int __cpu_disable(void) +{ + extern struct plat_smp_ops *mp_ops; /* private */ + + return mp_ops->cpu_disable(); +} + +static inline void __cpu_die(unsigned int cpu) +{ + extern struct plat_smp_ops *mp_ops; /* private */ + + mp_ops->cpu_die(cpu); +} + +extern void play_dead(void); +#endif + extern asmlinkage void smp_call_function_interrupt(void); extern void arch_send_call_function_single_ipi(int cpu); diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 1eaaa450e20..c09d681b718 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -50,10 +50,15 @@ */ void __noreturn cpu_idle(void) { + int cpu; + + /* CPU is going idle. */ + cpu = smp_processor_id(); + /* endless idle loop with no priority at all */ while (1) { tick_nohz_stop_sched_tick(1); - while (!need_resched()) { + while (!need_resched() && cpu_online(cpu)) { #ifdef CONFIG_MIPS_MT_SMTC extern void smtc_idle_loop_hook(void); @@ -62,6 +67,12 @@ void __noreturn cpu_idle(void) if (cpu_wait) (*cpu_wait)(); } +#ifdef CONFIG_HOTPLUG_CPU + if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map) && + (system_state == SYSTEM_RUNNING || + system_state == SYSTEM_BOOTING)) + play_dead(); +#endif tick_nohz_restart_sched_tick(); preempt_enable_no_resched(); schedule(); diff --git a/arch/mips/kernel/smp-up.c b/arch/mips/kernel/smp-up.c index 878e3733bbb..2508d55d68f 100644 --- a/arch/mips/kernel/smp-up.c +++ b/arch/mips/kernel/smp-up.c @@ -55,6 +55,18 @@ static void __init up_prepare_cpus(unsigned int max_cpus) { } +#ifdef CONFIG_HOTPLUG_CPU +static int up_cpu_disable(void) +{ + return -ENOSYS; +} + +static void up_cpu_die(unsigned int cpu) +{ + BUG(); +} +#endif + struct plat_smp_ops up_smp_ops = { .send_ipi_single = up_send_ipi_single, .send_ipi_mask = up_send_ipi_mask, @@ -64,4 +76,8 @@ struct plat_smp_ops up_smp_ops = { .boot_secondary = up_boot_secondary, .smp_setup = up_smp_setup, .prepare_cpus = up_prepare_cpus, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_disable = up_cpu_disable, + .cpu_die = up_cpu_die, +#endif }; diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 58f4679bbd4..bc7d9b05e2f 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -45,7 +45,7 @@ #include #endif /* CONFIG_MIPS_MT_SMTC */ -static volatile cpumask_t cpu_callin_map; /* Bitmask of started secondaries */ +volatile cpumask_t cpu_callin_map; /* Bitmask of started secondaries */ int __cpu_number_map[NR_CPUS]; /* Map physical to logical */ int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */ @@ -201,6 +201,8 @@ void __devinit smp_prepare_boot_cpu(void) * and keep control until "cpu_online(cpu)" is set. Note: cpu is * physical, not logical. */ +static struct task_struct *cpu_idle_thread[NR_CPUS]; + int __cpuinit __cpu_up(unsigned int cpu) { struct task_struct *idle; @@ -210,9 +212,16 @@ int __cpuinit __cpu_up(unsigned int cpu) * The following code is purely to make sure * Linux can schedule processes on this slave. */ - idle = fork_idle(cpu); - if (IS_ERR(idle)) - panic(KERN_ERR "Fork failed for CPU %d", cpu); + if (!cpu_idle_thread[cpu]) { + idle = fork_idle(cpu); + cpu_idle_thread[cpu] = idle; + + if (IS_ERR(idle)) + panic(KERN_ERR "Fork failed for CPU %d", cpu); + } else { + idle = cpu_idle_thread[cpu]; + init_idle(idle, cpu); + } mp_ops->boot_secondary(cpu, idle); diff --git a/arch/mips/kernel/topology.c b/arch/mips/kernel/topology.c index 660e44ed44d..cf3eb61fad1 100644 --- a/arch/mips/kernel/topology.c +++ b/arch/mips/kernel/topology.c @@ -17,7 +17,10 @@ static int __init topology_init(void) #endif /* CONFIG_NUMA */ for_each_present_cpu(i) { - ret = register_cpu(&per_cpu(cpu_devices, i), i); + struct cpu *c = &per_cpu(cpu_devices, i); + + c->hotpluggable = 1; + ret = register_cpu(c, i); if (ret) printk(KERN_WARNING "topology_init: register_cpu %d " "failed (%d)\n", i, ret); -- cgit v1.2.3-70-g09d2 From 9801b321ecdb6708365b6825bf728c8e433fca00 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 23 Jun 2009 10:20:56 +0100 Subject: MIPS: SMP: Allow suspend and hibernation if CPU hotplug is available The SMP implementation of suspend and hibernate depends on CPU hotplugging. In the past we didn't have CPU hotplug so suspend and hibernation were not possible on SMP systems. Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index eb7e8d795c6..3cce4ed5473 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2145,11 +2145,11 @@ menu "Power management options" config ARCH_HIBERNATION_POSSIBLE def_bool y - depends on !SMP + depends on SYS_SUPPORTS_HOTPLUG_CPU config ARCH_SUSPEND_POSSIBLE def_bool y - depends on !SMP + depends on SYS_SUPPORTS_HOTPLUG_CPU source "kernel/power/Kconfig" -- cgit v1.2.3-70-g09d2 From 773cb77d0e32f0a3c36edf5aaeb9642c18038cd2 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 23 Jun 2009 10:36:38 +0100 Subject: MIPS: Cavium: Add CPU hotplugging code. Thanks to Cavium Inc. for the code contribution and help. Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 + arch/mips/cavium-octeon/octeon-irq.c | 59 +++++++++ arch/mips/cavium-octeon/octeon_boot.h | 70 ++++++++++ arch/mips/cavium-octeon/smp.c | 234 +++++++++++++++++++++++++++++++++- arch/mips/include/asm/smp.h | 2 +- 5 files changed, 365 insertions(+), 2 deletions(-) create mode 100644 arch/mips/cavium-octeon/octeon_boot.h (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 3cce4ed5473..8c4be1f301c 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -601,6 +601,7 @@ config CAVIUM_OCTEON_SIMULATOR select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_HIGHMEM + select SYS_SUPPORTS_HOTPLUG_CPU select SYS_HAS_CPU_CAVIUM_OCTEON help The Octeon simulator is software performance model of the Cavium @@ -615,6 +616,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_HIGHMEM + select SYS_SUPPORTS_HOTPLUG_CPU select SYS_HAS_EARLY_PRINTK select SYS_HAS_CPU_CAVIUM_OCTEON select SWAP_IO_SPACE diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 3090ee37e10..384f1842bfb 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -501,3 +501,62 @@ asmlinkage void plat_irq_dispatch(void) } } } + +#ifdef CONFIG_HOTPLUG_CPU +static int is_irq_enabled_on_cpu(unsigned int irq, unsigned int cpu) +{ + unsigned int isset; +#ifdef CONFIG_SMP + int coreid = cpu_logical_map(cpu); +#else + int coreid = cvmx_get_core_num(); +#endif + int bit = (irq < OCTEON_IRQ_WDOG0) ? + irq - OCTEON_IRQ_WORKQ0 : irq - OCTEON_IRQ_WDOG0; + if (irq < 64) { + isset = (cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)) & + (1ull << bit)) >> bit; + } else { + isset = (cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)) & + (1ull << bit)) >> bit; + } + return isset; +} + +void fixup_irqs(void) +{ + int irq; + + for (irq = OCTEON_IRQ_SW0; irq <= OCTEON_IRQ_TIMER; irq++) + octeon_irq_core_disable_local(irq); + + for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_GPIO15; irq++) { + if (is_irq_enabled_on_cpu(irq, smp_processor_id())) { + /* ciu irq migrates to next cpu */ + octeon_irq_chip_ciu0.disable(irq); + octeon_irq_ciu0_set_affinity(irq, &cpu_online_map); + } + } + +#if 0 + for (irq = OCTEON_IRQ_MBOX0; irq <= OCTEON_IRQ_MBOX1; irq++) + octeon_irq_mailbox_mask(irq); +#endif + for (irq = OCTEON_IRQ_UART0; irq <= OCTEON_IRQ_BOOTDMA; irq++) { + if (is_irq_enabled_on_cpu(irq, smp_processor_id())) { + /* ciu irq migrates to next cpu */ + octeon_irq_chip_ciu0.disable(irq); + octeon_irq_ciu0_set_affinity(irq, &cpu_online_map); + } + } + + for (irq = OCTEON_IRQ_UART2; irq <= OCTEON_IRQ_RESERVED135; irq++) { + if (is_irq_enabled_on_cpu(irq, smp_processor_id())) { + /* ciu irq migrates to next cpu */ + octeon_irq_chip_ciu1.disable(irq); + octeon_irq_ciu1_set_affinity(irq, &cpu_online_map); + } + } +} + +#endif /* CONFIG_HOTPLUG_CPU */ diff --git a/arch/mips/cavium-octeon/octeon_boot.h b/arch/mips/cavium-octeon/octeon_boot.h new file mode 100644 index 00000000000..0f7f84accf9 --- /dev/null +++ b/arch/mips/cavium-octeon/octeon_boot.h @@ -0,0 +1,70 @@ +/* + * (C) Copyright 2004, 2005 Cavium Networks + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __OCTEON_BOOT_H__ +#define __OCTEON_BOOT_H__ + +#include + +struct boot_init_vector { + uint32_t stack_addr; + uint32_t code_addr; + uint32_t app_start_func_addr; + uint32_t k0_val; + uint32_t flags; + uint32_t boot_info_addr; + uint32_t pad; + uint32_t pad2; +}; + +/* similar to bootloader's linux_app_boot_info but without global data */ +struct linux_app_boot_info { + uint32_t labi_signature; + uint32_t start_core0_addr; + uint32_t avail_coremask; + uint32_t pci_console_active; + uint32_t icache_prefetch_disable; + uint32_t InitTLBStart_addr; + uint32_t start_app_addr; + uint32_t cur_exception_base; + uint32_t no_mark_private_data; + uint32_t compact_flash_common_base_addr; + uint32_t compact_flash_attribute_base_addr; + uint32_t led_display_base_addr; +}; + +/* If not to copy a lot of bootloader's structures + here is only offset of requested member */ +#define AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK 0x765c + +/* hardcoded in bootloader */ +#define LABI_ADDR_IN_BOOTLOADER 0x700 + +#define LINUX_APP_BOOT_BLOCK_NAME "linux-app-boot" + +#define LABI_SIGNATURE 0xAABBCCDD + +/* from uboot-headers/octeon_mem_map.h */ +#define EXCEPTION_BASE_INCR (4 * 1024) + /* Increment size for exception base addresses (4k minimum) */ +#define EXCEPTION_BASE_BASE 0 +#define BOOTLOADER_PRIV_DATA_BASE (EXCEPTION_BASE_BASE + 0x800) +#define BOOTLOADER_BOOT_VECTOR (BOOTLOADER_PRIV_DATA_BASE) + +#endif /* __OCTEON_BOOT_H__ */ diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 24e0ad63980..0b891a9c625 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -5,6 +5,7 @@ * * Copyright (C) 2004-2008 Cavium Networks */ +#include #include #include #include @@ -19,10 +20,16 @@ #include +#include "octeon_boot.h" + volatile unsigned long octeon_processor_boot = 0xff; volatile unsigned long octeon_processor_sp; volatile unsigned long octeon_processor_gp; +#ifdef CONFIG_HOTPLUG_CPU +static unsigned int InitTLBStart_addr; +#endif + static irqreturn_t mailbox_interrupt(int irq, void *dev_id) { const int coreid = cvmx_get_core_num(); @@ -67,8 +74,28 @@ static inline void octeon_send_ipi_mask(cpumask_t mask, unsigned int action) } /** - * Detect available CPUs, populate phys_cpu_present_map + * Detect available CPUs, populate cpu_possible_map */ +static void octeon_smp_hotplug_setup(void) +{ +#ifdef CONFIG_HOTPLUG_CPU + uint32_t labi_signature; + + labi_signature = + cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, + LABI_ADDR_IN_BOOTLOADER + + offsetof(struct linux_app_boot_info, + labi_signature))); + if (labi_signature != LABI_SIGNATURE) + pr_err("The bootloader version on this board is incorrect\n"); + InitTLBStart_addr = + cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, + LABI_ADDR_IN_BOOTLOADER + + offsetof(struct linux_app_boot_info, + InitTLBStart_addr))); +#endif +} + static void octeon_smp_setup(void) { const int coreid = cvmx_get_core_num(); @@ -91,6 +118,9 @@ static void octeon_smp_setup(void) cpus++; } } + cpu_present_map = cpu_possible_map; + + octeon_smp_hotplug_setup(); } /** @@ -128,6 +158,17 @@ static void octeon_init_secondary(void) const int coreid = cvmx_get_core_num(); union cvmx_ciu_intx_sum0 interrupt_enable; +#ifdef CONFIG_HOTPLUG_CPU + unsigned int cur_exception_base; + + cur_exception_base = cvmx_read64_uint32( + CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, + LABI_ADDR_IN_BOOTLOADER + + offsetof(struct linux_app_boot_info, + cur_exception_base))); + /* cur_exception_base is incremented in bootloader after setting */ + write_c0_ebase((unsigned int)(cur_exception_base - EXCEPTION_BASE_INCR)); +#endif octeon_check_cpu_bist(); octeon_init_cvmcount(); /* @@ -199,6 +240,193 @@ static void octeon_cpus_done(void) #endif } +#ifdef CONFIG_HOTPLUG_CPU + +/* State of each CPU. */ +DEFINE_PER_CPU(int, cpu_state); + +extern void fixup_irqs(void); + +static DEFINE_SPINLOCK(smp_reserve_lock); + +static int octeon_cpu_disable(void) +{ + unsigned int cpu = smp_processor_id(); + + if (cpu == 0) + return -EBUSY; + + spin_lock(&smp_reserve_lock); + + cpu_clear(cpu, cpu_online_map); + cpu_clear(cpu, cpu_callin_map); + local_irq_disable(); + fixup_irqs(); + local_irq_enable(); + + flush_cache_all(); + local_flush_tlb_all(); + + spin_unlock(&smp_reserve_lock); + + return 0; +} + +static void octeon_cpu_die(unsigned int cpu) +{ + int coreid = cpu_logical_map(cpu); + uint32_t avail_coremask; + struct cvmx_bootmem_named_block_desc *block_desc; + +#ifdef CONFIG_CAVIUM_OCTEON_WATCHDOG + /* Disable the watchdog */ + cvmx_ciu_wdogx_t ciu_wdog; + ciu_wdog.u64 = cvmx_read_csr(CVMX_CIU_WDOGX(cpu)); + ciu_wdog.s.mode = 0; + cvmx_write_csr(CVMX_CIU_WDOGX(cpu), ciu_wdog.u64); +#endif + + while (per_cpu(cpu_state, cpu) != CPU_DEAD) + cpu_relax(); + + /* + * This is a bit complicated strategics of getting/settig available + * cores mask, copied from bootloader + */ + /* LINUX_APP_BOOT_BLOCK is initialized in bootoct binary */ + block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME); + + if (!block_desc) { + avail_coremask = + cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, + LABI_ADDR_IN_BOOTLOADER + + offsetof + (struct linux_app_boot_info, + avail_coremask))); + } else { /* alternative, already initialized */ + avail_coremask = + cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, + block_desc->base_addr + + AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK)); + } + + avail_coremask |= 1 << coreid; + + /* Setting avail_coremask for bootoct binary */ + if (!block_desc) { + cvmx_write64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, + LABI_ADDR_IN_BOOTLOADER + + offsetof(struct linux_app_boot_info, + avail_coremask)), + avail_coremask); + } else { + cvmx_write64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, + block_desc->base_addr + + AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK), + avail_coremask); + } + + pr_info("Reset core %d. Available Coremask = %x \n", coreid, + avail_coremask); + cvmx_write_csr(CVMX_CIU_PP_RST, 1 << coreid); + cvmx_write_csr(CVMX_CIU_PP_RST, 0); +} + +void play_dead(void) +{ + int coreid = cvmx_get_core_num(); + + idle_task_exit(); + octeon_processor_boot = 0xff; + per_cpu(cpu_state, coreid) = CPU_DEAD; + + while (1) /* core will be reset here */ + ; +} + +extern void kernel_entry(unsigned long arg1, ...); + +static void start_after_reset(void) +{ + kernel_entry(0, 0, 0); /* set a2 = 0 for secondary core */ +} + +int octeon_update_boot_vector(unsigned int cpu) +{ + + int coreid = cpu_logical_map(cpu); + unsigned int avail_coremask; + struct cvmx_bootmem_named_block_desc *block_desc; + struct boot_init_vector *boot_vect = + (struct boot_init_vector *) cvmx_phys_to_ptr(0x0 + + BOOTLOADER_BOOT_VECTOR); + + block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME); + + if (!block_desc) { + avail_coremask = + cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, + LABI_ADDR_IN_BOOTLOADER + + offsetof(struct linux_app_boot_info, + avail_coremask))); + } else { /* alternative, already initialized */ + avail_coremask = + cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, + block_desc->base_addr + + AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK)); + } + + if (!(avail_coremask & (1 << coreid))) { + /* core not available, assume, that catched by simple-executive */ + cvmx_write_csr(CVMX_CIU_PP_RST, 1 << coreid); + cvmx_write_csr(CVMX_CIU_PP_RST, 0); + } + + boot_vect[coreid].app_start_func_addr = + (uint32_t) (unsigned long) start_after_reset; + boot_vect[coreid].code_addr = InitTLBStart_addr; + + CVMX_SYNC; + + cvmx_write_csr(CVMX_CIU_NMI, (1 << coreid) & avail_coremask); + + return 0; +} + +static int __cpuinit octeon_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + + switch (action) { + case CPU_UP_PREPARE: + octeon_update_boot_vector(cpu); + break; + case CPU_ONLINE: + pr_info("Cpu %d online\n", cpu); + break; + case CPU_DEAD: + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block __cpuinitdata octeon_cpu_notifier = { + .notifier_call = octeon_cpu_callback, +}; + +static int __cpuinit register_cavium_notifier(void) +{ + register_hotcpu_notifier(&octeon_cpu_notifier); + + return 0; +} + +late_initcall(register_cavium_notifier); + +#endif /* CONFIG_HOTPLUG_CPU */ + struct plat_smp_ops octeon_smp_ops = { .send_ipi_single = octeon_send_ipi_single, .send_ipi_mask = octeon_send_ipi_mask, @@ -208,4 +436,8 @@ struct plat_smp_ops octeon_smp_ops = { .boot_secondary = octeon_boot_secondary, .smp_setup = octeon_smp_setup, .prepare_cpus = octeon_prepare_cpus, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_disable = octeon_cpu_disable, + .cpu_die = octeon_cpu_die, +#endif }; diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h index 01f813dc388..aaa2d4ab26d 100644 --- a/arch/mips/include/asm/smp.h +++ b/arch/mips/include/asm/smp.h @@ -41,7 +41,7 @@ extern int __cpu_logical_map[NR_CPUS]; /* Octeon - Tell another core to flush its icache */ #define SMP_ICACHE_FLUSH 0x4 -extern cpumask_t cpu_callin_map; +extern volatile cpumask_t cpu_callin_map; extern void asmlinkage smp_bootstrap(void); -- cgit v1.2.3-70-g09d2