ARM: rockchip: Add cpu hotplug support for RK3XXX SoCs
Subsystems (3)
PATCH 1/1 ARM: rockchip: Add cpu hotplug support for RK3XXX SoCs
Adds ability to shutdown all CPUs except the first one (since it might be special for a lot of platforms). It is now possible to use kexec which requires such a feature.
--- arch/arm/mach-rockchip/platsmp.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)
arch/arm/mach-rockchip/platsmp.c +31 -0
@@ -21,6 +21,7 @@#include <linux/of_address.h> #include <asm/cacheflush.h> +#include <asm/cp15.h> #include <asm/smp_scu.h> #include <asm/smp_plat.h> #include <asm/mach/map.h>
@@ -178,8 +179,38 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)pmu_set_power_domain (0 + i, false); } +#ifdef CONFIG_HOTPLUG_CPU +static DECLARE_COMPLETION (cpu_died); + +static int rockchip_cpu_kill (unsigned int cpu) +{ +if (!wait_for_completion_timeout (&cpu_died,msecs_to_jiffies (1000 ))) { +pr_err ("CPU%d: didn't die correctly\n" , cpu); +return 0 ; + } +pmu_set_power_domain (0 + cpu, false); +return 1 ; +} + + +static void rockchip_cpu_die (unsigned int cpu) +{ +complete (&cpu_died); +flush_cache_louis (); + +v7_exit_coherency_flush (louis); + +while (1 ) +cpu_do_idle (); +} +#endif +static struct smp_operations rockchip_smp_ops__initdata = { .smp_prepare_cpus = rockchip_smp_prepare_cpus, .smp_boot_secondary = rockchip_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_kill = rockchip_cpu_kill, + .cpu_die = rockchip_cpu_die, +#endif };CPU_METHOD_OF_DECLARE (rk3066_smp,"rockchip,rk3066-smp" , &rockchip_smp_ops);
Signature · 1 line
1.9.1
PATCH 1/1 ARM: rockchip: Add cpu hotplug support for RK3XXX SoCs
arch/arm/mach-rockchip/platsmp.c static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus) · line 190
Quoted 8 lines · Romain Perier
arch/arm/mach-rockchip/platsmp.c +8
-0+static DECLARE_COMPLETION (cpu_died); + +static int rockchip_cpu_kill (unsigned int cpu) +{ +if (!wait_for_completion_timeout (&cpu_died,msecs_to_jiffies (1000 ))) { +pr_err ("CPU%d: didn't die correctly\n" , cpu); +return 0 ; + }
Please explain the point of this cpu_died thing.
I think you should read arch/arm/kernel/smp.c, searching for cpu_died in there.
Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up according to speedtest.net.
PATCH 1/1 ARM: rockchip: Add cpu hotplug support for RK3XXX SoCs
Hi all,
you're probably talking about __cpu_die at
http://lxr.free-electrons.com/source/arch/arm/kernel/smp.c#L223 . The problem being that the thread below which executes cpu_die completes the completion before executing smp_ops.cpu_die. So smp_ops.cpu_kill might be executed before smp_ops.cpu_die (in some cases cache coherency would not be turned off). Note that almost all SoCs do the same thing.
Quoted 14 lines · Russell King - ARM Linux
arch/arm/mach-rockchip/platsmp.c static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus) · line 190
Quoted 8 lines · Romain Perier
arch/arm/mach-rockchip/platsmp.c +8
-0+static DECLARE_COMPLETION (cpu_died); + +static int rockchip_cpu_kill (unsigned int cpu) +{ +if (!wait_for_completion_timeout (&cpu_died,msecs_to_jiffies (1000 ))) { +pr_err ("CPU%d: didn't die correctly\n" , cpu); +return 0 ; + }Please explain the point of this
cpu_diedthing.I think you should read
arch/arm/kernel/smp.c, searching forcpu_diedin there.
PATCH 1/1 ARM: rockchip: Add cpu hotplug support for RK3XXX SoCs
Quoted 6 lines · Romain Perier
you're probably talking about
__cpu_dieat
http://lxr.free-electrons.com/source/arch/arm/kernel/smp.c#L223 . The problem being that the thread below which executescpu_diecompletes the completion before executing smp_ops.cpu_die. So smp_ops.cpu_kill might be executed before smp_ops.cpu_die (in some cases cache coherency would not be turned off). Note that almost all SoCs do the same thing.
Look at what's happening:
CPU0 CPU1 wait_for_completion_timeout() idle_task_exit() flush_cache_louis() complete(&cpu_died);
At this point, it is safe for CPU1 to be powered down.
smp_ops.cpu_kill(cpu); flush_cache_louis(); smp_ops.cpu_die(cpu);
If we include your code at that point, then the sequence in totality becomes:
wait_for_completion_timeout() idle_task_exit() flush_cache_louis() complete(&cpu_died); --- rockchip_cpu_kill --- wait_for_completion_timeout() flush_cache_louis(); --- rockchip_cpu_die --- complete(&cpu_died); pmu_set_power_domain(0 + cpu, false); flush_cache_louis(); v7_exit_coherency_flush(louis); while(1) cpu_do_idle();
So, I repeat my question. What is the point of your additional wait in rockchip_cpu_kill() and complete in rockchip_cpu_die()?
Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up according to speedtest.net.
PATCH 1/1 ARM: rockchip: Add cpu hotplug support for RK3XXX SoCs
Le 18/07/2014 10:29, Russell King - ARM Linux a ?crit :
Quoted 39 lines · Romain Perier
Quoted 6 lines
you're probably talking about
__cpu_dieat
http://lxr.free-electrons.com/source/arch/arm/kernel/smp.c#L223 . The problem being that the thread below which executescpu_diecompletes the completion before executing smp_ops.cpu_die. So smp_ops.cpu_kill might be executed before smp_ops.cpu_die (in some cases cache coherency would not be turned off). Note that almost all SoCs do the same thing.Look at what's happening:
CPU0 CPU1 wait_for_completion_timeout() idle_task_exit() flush_cache_louis() complete(&cpu_died);At this point, it is safe for CPU1 to be powered down.
smp_ops.cpu_kill(cpu); flush_cache_louis(); smp_ops.cpu_die(cpu);If we include your code at that point, then the sequence in totality becomes:
wait_for_completion_timeout() idle_task_exit() flush_cache_louis() complete(&cpu_died); --- rockchip_cpu_kill --- wait_for_completion_timeout() flush_cache_louis(); --- rockchip_cpu_die --- complete(&cpu_died); pmu_set_power_domain(0 + cpu, false); flush_cache_louis(); v7_exit_coherency_flush(louis); while(1) cpu_do_idle();
Quoted 3 lines
So, I repeat my question. What is the point of your additional wait in
rockchip_cpu_kill()and complete inrockchip_cpu_die()?
Mhhh... you're right... my bad ! So either smp_ops.cpu_kill(cpu) is executed before smp_ops.cpu_die and in this case it is safe to power down the cpu. or smp_ops.cpu_die(cpu) is executed before smp_ops.cpu_kill(due) and it is safe too.
I will send a new patch (v2)
Romain