X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=arch%2Farm%2Fmach-mvebu%2Fplatsmp.c;h=f278acebeaebf12c2a510a4f9e9404763c4a2acc;hb=ba3ec5780bba27819bbc4f669e6c77418a00f14b;hp=4880b0f7036243257973fd92fb3bb5322d17e470;hpb=ee2d8ea1e9bb27989f4f157520500dd6c4d45347;p=firefly-linux-kernel-4.4.55.git diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c index 4880b0f70362..f278acebeaeb 100644 --- a/arch/arm/mach-mvebu/platsmp.c +++ b/arch/arm/mach-mvebu/platsmp.c @@ -79,6 +79,17 @@ static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle) hw_cpu = cpu_logical_map(cpu); mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_xp_secondary_startup); + + /* + * This is needed to wake up CPUs in the offline state after + * using CPU hotplug. + */ + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); + + /* + * This is needed to take secondary CPUs out of reset on the + * initial boot. + */ ret = mvebu_cpu_reset_deassert(hw_cpu); if (ret) { pr_warn("unable to boot CPU: %d\n", ret); @@ -88,6 +99,19 @@ static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle) return 0; } +/* + * When a CPU is brought back online, either through CPU hotplug, or + * because of the boot of a kexec'ed kernel, the PMSU configuration + * for this CPU might be in the deep idle state, preventing this CPU + * from receiving interrupts. Here, we therefore take out the current + * CPU from this state, which was entered by armada_xp_cpu_die() + * below. + */ +static void armada_xp_secondary_init(unsigned int cpu) +{ + armada_370_xp_pmsu_idle_exit(); +} + static void __init armada_xp_smp_init_cpus(void) { unsigned int ncores = num_possible_cpus(); @@ -123,12 +147,36 @@ static void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus) panic("The address for the BootROM is incorrect"); } +#ifdef CONFIG_HOTPLUG_CPU +static void armada_xp_cpu_die(unsigned int cpu) +{ + /* + * CPU hotplug is implemented by putting offline CPUs into the + * deep idle sleep state. + */ + armada_370_xp_pmsu_idle_enter(true); +} + +/* + * We need a dummy function, so that platform_can_cpu_hotplug() knows + * we support CPU hotplug. However, the function does not need to do + * anything, because CPUs going offline can enter the deep idle state + * by themselves, without any help from a still alive CPU. + */ +static int armada_xp_cpu_kill(unsigned int cpu) +{ + return 1; +} +#endif + struct smp_operations armada_xp_smp_ops __initdata = { .smp_init_cpus = armada_xp_smp_init_cpus, .smp_prepare_cpus = armada_xp_smp_prepare_cpus, .smp_boot_secondary = armada_xp_boot_secondary, + .smp_secondary_init = armada_xp_secondary_init, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = armada_xp_cpu_die, + .cpu_kill = armada_xp_cpu_kill, #endif };