From: Greg Kroah-Hartman Date: Mon, 1 Apr 2019 12:03:26 +0000 (+0200) Subject: 3.18-stable patches X-Git-Tag: v3.18.138~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=458f82ea2d2bd0cd19bb21683d90797a4d09c871;p=thirdparty%2Fkernel%2Fstable-queue.git 3.18-stable patches added patches: arm-imx6q-cpuidle-fix-bug-that-cpu-might-not-wake-up-at-expected-time.patch --- diff --git a/queue-3.18/arm-imx6q-cpuidle-fix-bug-that-cpu-might-not-wake-up-at-expected-time.patch b/queue-3.18/arm-imx6q-cpuidle-fix-bug-that-cpu-might-not-wake-up-at-expected-time.patch new file mode 100644 index 00000000000..3d74f4451bd --- /dev/null +++ b/queue-3.18/arm-imx6q-cpuidle-fix-bug-that-cpu-might-not-wake-up-at-expected-time.patch @@ -0,0 +1,77 @@ +From 91740fc8242b4f260cfa4d4536d8551804777fae Mon Sep 17 00:00:00 2001 +From: Kohji Okuno +Date: Tue, 26 Feb 2019 11:34:13 +0900 +Subject: ARM: imx6q: cpuidle: fix bug that CPU might not wake up at expected time + +From: Kohji Okuno + +commit 91740fc8242b4f260cfa4d4536d8551804777fae upstream. + +In the current cpuidle implementation for i.MX6q, the CPU that sets +'WAIT_UNCLOCKED' and the CPU that returns to 'WAIT_CLOCKED' are always +the same. While the CPU that sets 'WAIT_UNCLOCKED' is in IDLE state of +"WAIT", if the other CPU wakes up and enters IDLE state of "WFI" +istead of "WAIT", this CPU can not wake up at expired time. + Because, in the case of "WFI", the CPU must be waked up by the local +timer interrupt. But, while 'WAIT_UNCLOCKED' is set, the local timer +is stopped, when all CPUs execute "wfi" instruction. As a result, the +local timer interrupt is not fired. + In this situation, this CPU will wake up by IRQ different from local +timer. (e.g. broacast timer) + +So, this fix changes CPU to return to 'WAIT_CLOCKED'. + +Signed-off-by: Kohji Okuno +Fixes: e5f9dec8ff5f ("ARM: imx6q: support WAIT mode using cpuidle") +Cc: +Signed-off-by: Shawn Guo +Signed-off-by: Kohji Okuno +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/mach-imx/cpuidle-imx6q.c | 27 ++++++++++----------------- + 1 file changed, 10 insertions(+), 17 deletions(-) + +--- a/arch/arm/mach-imx/cpuidle-imx6q.c ++++ b/arch/arm/mach-imx/cpuidle-imx6q.c +@@ -15,30 +15,23 @@ + #include "cpuidle.h" + #include "hardware.h" + +-static atomic_t master = ATOMIC_INIT(0); +-static DEFINE_SPINLOCK(master_lock); ++static int num_idle_cpus = 0; ++static DEFINE_SPINLOCK(cpuidle_lock); + + static int imx6q_enter_wait(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) + { +- if (atomic_inc_return(&master) == num_online_cpus()) { +- /* +- * With this lock, we prevent other cpu to exit and enter +- * this function again and become the master. +- */ +- if (!spin_trylock(&master_lock)) +- goto idle; ++ spin_lock(&cpuidle_lock); ++ if (++num_idle_cpus == num_online_cpus()) + imx6q_set_lpm(WAIT_UNCLOCKED); +- cpu_do_idle(); +- imx6q_set_lpm(WAIT_CLOCKED); +- spin_unlock(&master_lock); +- goto done; +- } ++ spin_unlock(&cpuidle_lock); + +-idle: + cpu_do_idle(); +-done: +- atomic_dec(&master); ++ ++ spin_lock(&cpuidle_lock); ++ if (num_idle_cpus-- == num_online_cpus()) ++ imx6q_set_lpm(WAIT_CLOCKED); ++ spin_unlock(&cpuidle_lock); + + return index; + } diff --git a/queue-3.18/series b/queue-3.18/series index 01e90f8119b..e4609a9be23 100644 --- a/queue-3.18/series +++ b/queue-3.18/series @@ -46,3 +46,4 @@ fs-proc-proc_sysctl.c-fix-null-pointer-dereference-in-put_links.patch gpio-adnp-fix-testing-wrong-value-in-adnp_gpio_direction_input.patch kvm-reject-device-ioctls-from-processes-other-than-the-vm-s-creator.patch xhci-fix-port-resume-done-detection-for-ss-ports-with-lpm-enabled.patch +arm-imx6q-cpuidle-fix-bug-that-cpu-might-not-wake-up-at-expected-time.patch