From 0c09360a7d91e688ce80826924995effa1bf5ce8 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Wed, 5 Jul 2017 20:34:01 +0300 Subject: MLK15034: ARM: cpuidle imx7d: Use a single counter for lpi flow The current code for deciding which CPU runs the complete lpi flow is too complicated. Since all enter/exit code now runs under the same lock we can just use a single non-atomic counter of cpus inside lpi. Another variable is used to make num_online_cpus() available to ASM code but idle code can treat it as a constant. Signed-off-by: Leonard Crestez --- arch/arm/mach-imx/cpuidle-imx7d.c | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) (limited to 'arch/arm/mach-imx/cpuidle-imx7d.c') diff --git a/arch/arm/mach-imx/cpuidle-imx7d.c b/arch/arm/mach-imx/cpuidle-imx7d.c index 740cbb2278ba..d54954aba734 100644 --- a/arch/arm/mach-imx/cpuidle-imx7d.c +++ b/arch/arm/mach-imx/cpuidle-imx7d.c @@ -62,10 +62,9 @@ struct imx7_cpuidle_pm_info { phys_addr_t pbase; /* The physical address of pm_info. */ phys_addr_t resume_addr; /* The physical resume address for asm code */ u32 pm_info_size; - int last_cpu; u32 ttbr; - u32 cpu1_wfi; - u32 lpi_enter; + u32 num_online_cpus; + u32 num_lpi_cpus; atomic_t val; atomic_t flag0; atomic_t flag1; @@ -78,7 +77,6 @@ struct imx7_cpuidle_pm_info { struct imx7_pm_base gic_dist_base; } __aligned(8); -static atomic_t master_lpi = ATOMIC_INIT(0); static atomic_t master_wait = ATOMIC_INIT(0); static void (*imx7d_wfi_in_iram_fn)(void __iomem *iram_vbase); @@ -151,9 +149,10 @@ static int imx7d_enter_low_power_idle(struct cpuidle_device *dev, imx_gpcv2_set_lpm_mode(WAIT_CLOCKED); } else { imx_pen_lock(dev->cpu); + ++cpuidle_pm_info->num_lpi_cpus; cpu_pm_enter(); - if (atomic_inc_return(&master_lpi) == num_online_cpus() && - cpuidle_pm_info->last_cpu == -1) { + if (cpuidle_pm_info->num_lpi_cpus == + cpuidle_pm_info->num_online_cpus) { /* * GPC will not wake on SGIs so check for them * manually here. At this point we know the other cpu @@ -167,26 +166,22 @@ static int imx7d_enter_low_power_idle(struct cpuidle_device *dev, imx_gpcv2_set_lpm_mode(WAIT_UNCLOCKED); imx_gpcv2_set_cpu_power_gate_in_idle(true); cpu_cluster_pm_enter(); - - cpuidle_pm_info->last_cpu = dev->cpu; - } else { imx_set_cpu_jump(dev->cpu, ca7_cpu_resume); } cpu_suspend(0, imx7d_idle_finish); - if (atomic_dec_return(&master_lpi) == (num_online_cpus() - 1)) { + if (cpuidle_pm_info->num_lpi_cpus == + cpuidle_pm_info->num_online_cpus) { cpu_cluster_pm_exit(); imx_gpcv2_set_cpu_power_gate_in_idle(false); imx_gpcv2_set_lpm_mode(WAIT_CLOCKED); } - if (cpuidle_pm_info->last_cpu == dev->cpu) - cpuidle_pm_info->last_cpu = -1; - skip_lpi_flow: cpu_pm_exit(); + --cpuidle_pm_info->num_lpi_cpus; imx_pen_unlock(dev->cpu); } @@ -227,11 +222,9 @@ static int cpu_hotplug_notify(struct notifier_block *self, unsigned long action, void *hcpu) { switch (action) { - case CPU_UP_PREPARE: - cpuidle_pm_info->cpu1_wfi = 0; - break; case CPU_DEAD: - cpuidle_pm_info->cpu1_wfi = 1; + case CPU_ONLINE: + cpuidle_pm_info->num_online_cpus = num_online_cpus(); break; } return NOTIFY_OK; @@ -316,13 +309,7 @@ int __init imx7d_cpuidle_init(void) cpuidle_pm_info->pbase = (phys_addr_t) wfi_iram_base_phys; cpuidle_pm_info->pm_info_size = sizeof(*cpuidle_pm_info); cpuidle_pm_info->resume_addr = virt_to_phys(ca7_cpu_resume); - if (num_online_cpus() == 1) - cpuidle_pm_info->cpu1_wfi = 1; - else - cpuidle_pm_info->cpu1_wfi = 0; - cpuidle_pm_info->lpi_enter = 0; - /* initialize the last cpu id to invalid here */ - cpuidle_pm_info->last_cpu = -1; + cpuidle_pm_info->num_online_cpus = num_online_cpus(); cpuidle_pm_info->ddrc_base.pbase = MX7D_DDRC_BASE_ADDR; cpuidle_pm_info->ddrc_base.vbase = -- cgit v1.2.3