aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mvebu/platsmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mvebu/platsmp.c')
-rw-r--r--arch/arm/mach-mvebu/platsmp.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c
index 88b976b31719..b6fa9f0c98b8 100644
--- a/arch/arm/mach-mvebu/platsmp.c
+++ b/arch/arm/mach-mvebu/platsmp.c
@@ -78,6 +78,17 @@ static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle)
78 78
79 hw_cpu = cpu_logical_map(cpu); 79 hw_cpu = cpu_logical_map(cpu);
80 mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_xp_secondary_startup); 80 mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_xp_secondary_startup);
81
82 /*
83 * This is needed to wake up CPUs in the offline state after
84 * using CPU hotplug.
85 */
86 arch_send_wakeup_ipi_mask(cpumask_of(cpu));
87
88 /*
89 * This is needed to take secondary CPUs out of reset on the
90 * initial boot.
91 */
81 ret = mvebu_cpu_reset_deassert(hw_cpu); 92 ret = mvebu_cpu_reset_deassert(hw_cpu);
82 if (ret) { 93 if (ret) {
83 pr_warn("unable to boot CPU: %d\n", ret); 94 pr_warn("unable to boot CPU: %d\n", ret);
@@ -87,6 +98,19 @@ static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle)
87 return 0; 98 return 0;
88} 99}
89 100
101/*
102 * When a CPU is brought back online, either through CPU hotplug, or
103 * because of the boot of a kexec'ed kernel, the PMSU configuration
104 * for this CPU might be in the deep idle state, preventing this CPU
105 * from receiving interrupts. Here, we therefore take out the current
106 * CPU from this state, which was entered by armada_xp_cpu_die()
107 * below.
108 */
109static void armada_xp_secondary_init(unsigned int cpu)
110{
111 armada_370_xp_pmsu_idle_exit();
112}
113
90static void __init armada_xp_smp_init_cpus(void) 114static void __init armada_xp_smp_init_cpus(void)
91{ 115{
92 unsigned int ncores = num_possible_cpus(); 116 unsigned int ncores = num_possible_cpus();
@@ -122,12 +146,36 @@ static void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus)
122 panic("The address for the BootROM is incorrect"); 146 panic("The address for the BootROM is incorrect");
123} 147}
124 148
149#ifdef CONFIG_HOTPLUG_CPU
150static void armada_xp_cpu_die(unsigned int cpu)
151{
152 /*
153 * CPU hotplug is implemented by putting offline CPUs into the
154 * deep idle sleep state.
155 */
156 armada_370_xp_pmsu_idle_enter(true);
157}
158
159/*
160 * We need a dummy function, so that platform_can_cpu_hotplug() knows
161 * we support CPU hotplug. However, the function does not need to do
162 * anything, because CPUs going offline can enter the deep idle state
163 * by themselves, without any help from a still alive CPU.
164 */
165static int armada_xp_cpu_kill(unsigned int cpu)
166{
167 return 1;
168}
169#endif
170
125struct smp_operations armada_xp_smp_ops __initdata = { 171struct smp_operations armada_xp_smp_ops __initdata = {
126 .smp_init_cpus = armada_xp_smp_init_cpus, 172 .smp_init_cpus = armada_xp_smp_init_cpus,
127 .smp_prepare_cpus = armada_xp_smp_prepare_cpus, 173 .smp_prepare_cpus = armada_xp_smp_prepare_cpus,
128 .smp_boot_secondary = armada_xp_boot_secondary, 174 .smp_boot_secondary = armada_xp_boot_secondary,
175 .smp_secondary_init = armada_xp_secondary_init,
129#ifdef CONFIG_HOTPLUG_CPU 176#ifdef CONFIG_HOTPLUG_CPU
130 .cpu_die = armada_xp_cpu_die, 177 .cpu_die = armada_xp_cpu_die,
178 .cpu_kill = armada_xp_cpu_kill,
131#endif 179#endif
132}; 180};
133 181