Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge commit 'smp-hotplug^{/omap2}' into for-linus

+81 -185
-20
arch/arm/mach-omap2/omap-smp.c
··· 69 69 .startup_addr = omap5_secondary_startup, 70 70 }; 71 71 72 - static DEFINE_SPINLOCK(boot_lock); 73 - 74 72 void __iomem *omap4_get_scu_base(void) 75 73 { 76 74 return cfg.scu_base; ··· 171 173 /* Enable ACR to allow for ICUALLU workaround */ 172 174 omap5_secondary_harden_predictor(); 173 175 } 174 - 175 - /* 176 - * Synchronise with the boot thread. 177 - */ 178 - spin_lock(&boot_lock); 179 - spin_unlock(&boot_lock); 180 176 } 181 177 182 178 static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle) ··· 178 186 static struct clockdomain *cpu1_clkdm; 179 187 static bool booted; 180 188 static struct powerdomain *cpu1_pwrdm; 181 - 182 - /* 183 - * Set synchronisation state between this boot processor 184 - * and the secondary one 185 - */ 186 - spin_lock(&boot_lock); 187 189 188 190 /* 189 191 * Update the AuxCoreBoot0 with boot state for secondary core. ··· 251 265 } 252 266 253 267 arch_send_wakeup_ipi_mask(cpumask_of(cpu)); 254 - 255 - /* 256 - * Now the secondary core is starting up let it run its 257 - * calibrations, then wait for it to finish 258 - */ 259 - spin_unlock(&boot_lock); 260 268 261 269 return 0; 262 270 }
-1
arch/arm/mach-realview/Makefile
··· 5 5 6 6 obj-y += realview-dt.o 7 7 obj-$(CONFIG_SMP) += platsmp-dt.o 8 - obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+30 -36
arch/arm/mach-realview/hotplug.c arch/arm/plat-versatile/hotplug.c
··· 1 1 /* 2 - * linux/arch/arm/mach-realview/hotplug.c 3 - * 4 2 * Copyright (C) 2002 ARM Ltd. 5 3 * All Rights Reserved 6 4 * 7 5 * This program is free software; you can redistribute it and/or modify 8 6 * it under the terms of the GNU General Public License version 2 as 9 7 * published by the Free Software Foundation. 8 + * 9 + * This hotplug implementation is _specific_ to the situation found on 10 + * ARM development platforms where there is _no_ possibility of actually 11 + * taking a CPU offline, resetting it, or otherwise. Real platforms must 12 + * NOT copy this code. 10 13 */ 11 14 #include <linux/kernel.h> 12 15 #include <linux/errno.h> 13 16 #include <linux/smp.h> 14 17 15 - #include <asm/cp15.h> 16 18 #include <asm/smp_plat.h> 19 + #include <asm/cp15.h> 17 20 18 - static inline void cpu_enter_lowpower(void) 21 + #include <plat/platsmp.h> 22 + 23 + static inline void versatile_immitation_enter_lowpower(unsigned int actrl_mask) 19 24 { 20 25 unsigned int v; 21 26 22 27 asm volatile( 23 - " mcr p15, 0, %1, c7, c5, 0\n" 28 + "mcr p15, 0, %1, c7, c5, 0\n" 24 29 " mcr p15, 0, %1, c7, c10, 4\n" 25 30 /* 26 31 * Turn off coherency 27 32 */ 28 33 " mrc p15, 0, %0, c1, c0, 1\n" 29 - " bic %0, %0, #0x20\n" 34 + " bic %0, %0, %3\n" 30 35 " mcr p15, 0, %0, c1, c0, 1\n" 31 36 " mrc p15, 0, %0, c1, c0, 0\n" 32 37 " bic %0, %0, %2\n" 33 38 " mcr p15, 0, %0, c1, c0, 0\n" 34 39 : "=&r" (v) 35 - : "r" (0), "Ir" (CR_C) 40 + : "r" (0), "Ir" (CR_C), "Ir" (actrl_mask) 36 41 : "cc"); 37 42 } 38 43 39 - static inline void cpu_leave_lowpower(void) 44 + static inline void versatile_immitation_leave_lowpower(unsigned int actrl_mask) 40 45 { 41 46 unsigned int v; 42 47 43 - asm volatile( "mrc p15, 0, %0, c1, c0, 0\n" 48 + asm volatile( 49 + "mrc p15, 0, %0, c1, c0, 0\n" 44 50 " orr %0, %0, %1\n" 45 51 " mcr p15, 0, %0, c1, c0, 0\n" 46 52 " mrc p15, 0, %0, c1, c0, 1\n" 47 - " orr %0, %0, #0x20\n" 53 + " orr %0, %0, %2\n" 48 54 " mcr p15, 0, %0, c1, c0, 1\n" 49 55 : "=&r" (v) 50 - : "Ir" (CR_C) 56 + : "Ir" (CR_C), "Ir" (actrl_mask) 51 57 : "cc"); 52 58 } 53 59 54 - static inline void platform_do_lowpower(unsigned int cpu, int *spurious) 60 + static inline void versatile_immitation_do_lowpower(unsigned int cpu, int *spurious) 55 61 { 56 62 /* 57 63 * there is no power-control hardware on this platform, so all 58 64 * we can do is put the core into WFI; this is safe as the calling 59 - * code will have already disabled interrupts 65 + * code will have already disabled interrupts. 66 + * 67 + * This code should not be used outside Versatile platforms. 60 68 */ 61 69 for (;;) { 62 - /* 63 - * here's the WFI 64 - */ 65 - asm(".word 0xe320f003\n" 66 - : 67 - : 68 - : "memory", "cc"); 70 + wfi(); 69 71 70 - if (pen_release == cpu_logical_map(cpu)) { 72 + if (versatile_cpu_release == cpu_logical_map(cpu)) { 71 73 /* 72 74 * OK, proper wakeup, we're done 73 75 */ ··· 88 86 } 89 87 90 88 /* 91 - * platform-specific code to shutdown a CPU 92 - * 93 - * Called with IRQs disabled 89 + * platform-specific code to shutdown a CPU. 90 + * This code supports immitation-style CPU hotplug for Versatile/Realview/ 91 + * Versatile Express platforms that are unable to do real CPU hotplug. 94 92 */ 95 - void realview_cpu_die(unsigned int cpu) 93 + void versatile_immitation_cpu_die(unsigned int cpu, unsigned int actrl_mask) 96 94 { 97 95 int spurious = 0; 98 96 99 - /* 100 - * we're ready for shutdown now, so do it 101 - */ 102 - cpu_enter_lowpower(); 103 - platform_do_lowpower(cpu, &spurious); 104 - 105 - /* 106 - * bring this CPU back into the world of cache 107 - * coherency, and then restore interrupts 108 - */ 109 - cpu_leave_lowpower(); 97 + versatile_immitation_enter_lowpower(actrl_mask); 98 + versatile_immitation_do_lowpower(cpu, &spurious); 99 + versatile_immitation_leave_lowpower(actrl_mask); 110 100 111 101 if (spurious) 112 102 pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
-1
arch/arm/mach-realview/hotplug.h
··· 1 - void realview_cpu_die(unsigned int cpu);
+7 -1
arch/arm/mach-realview/platsmp-dt.c
··· 17 17 #include <asm/smp_scu.h> 18 18 19 19 #include <plat/platsmp.h> 20 - #include "hotplug.h" 21 20 22 21 #define REALVIEW_SYS_FLAGSSET_OFFSET 0x30 23 22 ··· 77 78 regmap_write(map, REALVIEW_SYS_FLAGSSET_OFFSET, 78 79 __pa_symbol(versatile_secondary_startup)); 79 80 } 81 + 82 + #ifdef CONFIG_HOTPLUG_CPU 83 + static void realview_cpu_die(unsigned int cpu) 84 + { 85 + return versatile_immitation_cpu_die(cpu, 0x20); 86 + } 87 + #endif 80 88 81 89 static const struct smp_operations realview_dt_smp_ops __initconst = { 82 90 .smp_prepare_cpus = realview_smp_prepare_cpus,
-1
arch/arm/mach-vexpress/Makefile
··· 15 15 CFLAGS_tc2_pm.o += -march=armv7-a 16 16 CFLAGS_REMOVE_tc2_pm.o = -pg 17 17 obj-$(CONFIG_SMP) += platsmp.o 18 - obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 19 18 20 19 obj-$(CONFIG_ARCH_MPS2) += v2m-mps2.o
-2
arch/arm/mach-vexpress/core.h
··· 1 1 bool vexpress_smp_init_ops(void); 2 2 3 3 extern const struct smp_operations vexpress_smp_dt_ops; 4 - 5 - extern void vexpress_cpu_die(unsigned int cpu);
-108
arch/arm/mach-vexpress/hotplug.c
··· 1 - /* 2 - * linux/arch/arm/mach-realview/hotplug.c 3 - * 4 - * Copyright (C) 2002 ARM Ltd. 5 - * All Rights Reserved 6 - * 7 - * This program is free software; you can redistribute it and/or modify 8 - * it under the terms of the GNU General Public License version 2 as 9 - * published by the Free Software Foundation. 10 - */ 11 - #include <linux/kernel.h> 12 - #include <linux/errno.h> 13 - #include <linux/smp.h> 14 - 15 - #include <asm/smp_plat.h> 16 - #include <asm/cp15.h> 17 - 18 - #include "core.h" 19 - 20 - static inline void cpu_enter_lowpower(void) 21 - { 22 - unsigned int v; 23 - 24 - asm volatile( 25 - "mcr p15, 0, %1, c7, c5, 0\n" 26 - " mcr p15, 0, %1, c7, c10, 4\n" 27 - /* 28 - * Turn off coherency 29 - */ 30 - " mrc p15, 0, %0, c1, c0, 1\n" 31 - " bic %0, %0, %3\n" 32 - " mcr p15, 0, %0, c1, c0, 1\n" 33 - " mrc p15, 0, %0, c1, c0, 0\n" 34 - " bic %0, %0, %2\n" 35 - " mcr p15, 0, %0, c1, c0, 0\n" 36 - : "=&r" (v) 37 - : "r" (0), "Ir" (CR_C), "Ir" (0x40) 38 - : "cc"); 39 - } 40 - 41 - static inline void cpu_leave_lowpower(void) 42 - { 43 - unsigned int v; 44 - 45 - asm volatile( 46 - "mrc p15, 0, %0, c1, c0, 0\n" 47 - " orr %0, %0, %1\n" 48 - " mcr p15, 0, %0, c1, c0, 0\n" 49 - " mrc p15, 0, %0, c1, c0, 1\n" 50 - " orr %0, %0, %2\n" 51 - " mcr p15, 0, %0, c1, c0, 1\n" 52 - : "=&r" (v) 53 - : "Ir" (CR_C), "Ir" (0x40) 54 - : "cc"); 55 - } 56 - 57 - static inline void platform_do_lowpower(unsigned int cpu, int *spurious) 58 - { 59 - /* 60 - * there is no power-control hardware on this platform, so all 61 - * we can do is put the core into WFI; this is safe as the calling 62 - * code will have already disabled interrupts 63 - */ 64 - for (;;) { 65 - wfi(); 66 - 67 - if (pen_release == cpu_logical_map(cpu)) { 68 - /* 69 - * OK, proper wakeup, we're done 70 - */ 71 - break; 72 - } 73 - 74 - /* 75 - * Getting here, means that we have come out of WFI without 76 - * having been woken up - this shouldn't happen 77 - * 78 - * Just note it happening - when we're woken, we can report 79 - * its occurrence. 80 - */ 81 - (*spurious)++; 82 - } 83 - } 84 - 85 - /* 86 - * platform-specific code to shutdown a CPU 87 - * 88 - * Called with IRQs disabled 89 - */ 90 - void vexpress_cpu_die(unsigned int cpu) 91 - { 92 - int spurious = 0; 93 - 94 - /* 95 - * we're ready for shutdown now, so do it 96 - */ 97 - cpu_enter_lowpower(); 98 - platform_do_lowpower(cpu, &spurious); 99 - 100 - /* 101 - * bring this CPU back into the world of cache 102 - * coherency, and then restore interrupts 103 - */ 104 - cpu_leave_lowpower(); 105 - 106 - if (spurious) 107 - pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); 108 - }
+7
arch/arm/mach-vexpress/platsmp.c
··· 82 82 vexpress_flags_set(__pa_symbol(versatile_secondary_startup)); 83 83 } 84 84 85 + #ifdef CONFIG_HOTPLUG_CPU 86 + static void vexpress_cpu_die(unsigned int cpu) 87 + { 88 + versatile_immitation_cpu_die(cpu, 0x40); 89 + } 90 + #endif 91 + 85 92 const struct smp_operations vexpress_smp_dt_ops __initconst = { 86 93 .smp_prepare_cpus = vexpress_smp_dt_prepare_cpus, 87 94 .smp_secondary_init = versatile_secondary_init,
+1
arch/arm/plat-versatile/Makefile
··· 2 2 3 3 obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o 4 4 obj-$(CONFIG_SMP) += headsmp.o platsmp.o 5 + obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+1 -1
arch/arm/plat-versatile/headsmp.S
··· 37 37 38 38 .align 39 39 1: .long . 40 - .long pen_release 40 + .long versatile_cpu_release 41 41 ENDPROC(versatile_secondary_startup)
+2
arch/arm/plat-versatile/include/plat/platsmp.h
··· 8 8 * it under the terms of the GNU General Public License version 2 as 9 9 * published by the Free Software Foundation. 10 10 */ 11 + extern volatile int versatile_cpu_release; 11 12 12 13 extern void versatile_secondary_startup(void); 13 14 extern void versatile_secondary_init(unsigned int cpu); 14 15 extern int versatile_boot_secondary(unsigned int cpu, struct task_struct *idle); 16 + void versatile_immitation_cpu_die(unsigned int cpu, unsigned int actrl_mask);
+33 -14
arch/arm/plat-versatile/platsmp.c
··· 7 7 * This program is free software; you can redistribute it and/or modify 8 8 * it under the terms of the GNU General Public License version 2 as 9 9 * published by the Free Software Foundation. 10 + * 11 + * This code is specific to the hardware found on ARM Realview and 12 + * Versatile Express platforms where the CPUs are unable to be individually 13 + * woken, and where there is no way to hot-unplug CPUs. Real platforms 14 + * should not copy this code. 10 15 */ 11 16 #include <linux/init.h> 12 17 #include <linux/errno.h> ··· 26 21 #include <plat/platsmp.h> 27 22 28 23 /* 29 - * Write pen_release in a way that is guaranteed to be visible to all 30 - * observers, irrespective of whether they're taking part in coherency 24 + * versatile_cpu_release controls the release of CPUs from the holding 25 + * pen in headsmp.S, which exists because we are not always able to 26 + * control the release of individual CPUs from the board firmware. 27 + * Production platforms do not need this. 28 + */ 29 + volatile int versatile_cpu_release = -1; 30 + 31 + /* 32 + * Write versatile_cpu_release in a way that is guaranteed to be visible to 33 + * all observers, irrespective of whether they're taking part in coherency 31 34 * or not. This is necessary for the hotplug code to work reliably. 32 35 */ 33 - static void write_pen_release(int val) 36 + static void versatile_write_cpu_release(int val) 34 37 { 35 - pen_release = val; 38 + versatile_cpu_release = val; 36 39 smp_wmb(); 37 - sync_cache_w(&pen_release); 40 + sync_cache_w(&versatile_cpu_release); 38 41 } 39 42 40 - static DEFINE_SPINLOCK(boot_lock); 43 + /* 44 + * versatile_lock exists to avoid running the loops_per_jiffy delay loop 45 + * calibrations on the secondary CPU while the requesting CPU is using 46 + * the limited-bandwidth bus - which affects the calibration value. 47 + * Production platforms do not need this. 48 + */ 49 + static DEFINE_RAW_SPINLOCK(versatile_lock); 41 50 42 51 void versatile_secondary_init(unsigned int cpu) 43 52 { ··· 59 40 * let the primary processor know we're out of the 60 41 * pen, then head off into the C entry point 61 42 */ 62 - write_pen_release(-1); 43 + versatile_write_cpu_release(-1); 63 44 64 45 /* 65 46 * Synchronise with the boot thread. 66 47 */ 67 - spin_lock(&boot_lock); 68 - spin_unlock(&boot_lock); 48 + raw_spin_lock(&versatile_lock); 49 + raw_spin_unlock(&versatile_lock); 69 50 } 70 51 71 52 int versatile_boot_secondary(unsigned int cpu, struct task_struct *idle) ··· 76 57 * Set synchronisation state between this boot processor 77 58 * and the secondary one 78 59 */ 79 - spin_lock(&boot_lock); 60 + raw_spin_lock(&versatile_lock); 80 61 81 62 /* 82 63 * This is really belt and braces; we hold unintended secondary ··· 84 65 * since we haven't sent them a soft interrupt, they shouldn't 85 66 * be there. 86 67 */ 87 - write_pen_release(cpu_logical_map(cpu)); 68 + versatile_write_cpu_release(cpu_logical_map(cpu)); 88 69 89 70 /* 90 71 * Send the secondary CPU a soft interrupt, thereby causing ··· 96 77 timeout = jiffies + (1 * HZ); 97 78 while (time_before(jiffies, timeout)) { 98 79 smp_rmb(); 99 - if (pen_release == -1) 80 + if (versatile_cpu_release == -1) 100 81 break; 101 82 102 83 udelay(10); ··· 106 87 * now the secondary core is starting up let it run its 107 88 * calibrations, then wait for it to finish 108 89 */ 109 - spin_unlock(&boot_lock); 90 + raw_spin_unlock(&versatile_lock); 110 91 111 - return pen_release != -1 ? -ENOSYS : 0; 92 + return versatile_cpu_release != -1 ? -ENOSYS : 0; 112 93 }