From 9cd75e13de2dcf32ecc21c7f277cff3c0ced059e Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 May 2012 17:59:47 +0000 Subject: powerpc: Fix broken cpu_idle_wait() implementation commit 771dae818 (powerpc/cpuidle: Add cpu_idle_wait() to allow switching of idle routines) implemented cpu_idle_wait() for powerpc. The changelog says: "The equivalent routine for x86 is in arch/x86/kernel/process.c but the powerpc implementation is different.": Unfortunately the changelog is completely useless as it does not tell _WHY_ it is different. Aside of being different the implementation is patently wrong. The rescheduling IPI is async. That means that there is no guarantee, that the other cores have executed the IPI when cpu_idle_wait() returns. But that's the whole purpose of this function: to guarantee that no CPU uses the old idle handler anymore. Use the smp_functional_call() based implementation, which fulfils the requirements. [ This code is going to replaced by a core version to remove all the pointless copies in arch/*, but this one should go to stable ] Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra Cc: Deepthi Dharwar Cc: Trinabh Gupta Cc: Arun R Bharadwaj Acked-by: Benjamin Herrenschmidt Link: http://lkml.kernel.org/r/20120507175651.980164748@linutronix.de Cc: stable@vger.kernel.org --- arch/powerpc/kernel/idle.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'arch/powerpc/kernel/idle.c') diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c index 6d2209ac0c4..04d79093d7a 100644 --- a/arch/powerpc/kernel/idle.c +++ b/arch/powerpc/kernel/idle.c @@ -113,6 +113,9 @@ void cpu_idle(void) } } +static void do_nothing(void *unused) +{ +} /* * cpu_idle_wait - Used to ensure that all the CPUs come out of the old @@ -123,16 +126,9 @@ void cpu_idle(void) */ void cpu_idle_wait(void) { - int cpu; smp_mb(); - - /* kick all the CPUs so that they exit out of old idle routine */ - get_online_cpus(); - for_each_online_cpu(cpu) { - if (cpu != smp_processor_id()) - smp_send_reschedule(cpu); - } - put_online_cpus(); + /* kick all the CPUs so that they exit out of pm_idle */ + smp_call_function(do_nothing, NULL, 1); } EXPORT_SYMBOL_GPL(cpu_idle_wait); -- cgit v1.2.3-70-g09d2 From c9b92b840705542a1ae50b5407154a5595d17359 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 May 2012 17:59:50 +0000 Subject: powerpc: Remove unused cpu_idle_wait() cpuidle uses a generic function now. Remove the cruft. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Benjamin Herrenschmidt Link: http://lkml.kernel.org/r/20120507175652.330322737@linutronix.de --- arch/powerpc/Kconfig | 4 ---- arch/powerpc/include/asm/processor.h | 1 - arch/powerpc/kernel/idle.c | 19 ------------------- 3 files changed, 24 deletions(-) (limited to 'arch/powerpc/kernel/idle.c') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index c8155350836..296e4f99797 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -87,10 +87,6 @@ config ARCH_HAS_ILOG2_U64 bool default y if 64BIT -config ARCH_HAS_CPU_IDLE_WAIT - bool - default y - config GENERIC_HWEIGHT bool default y diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 8e2d0371fe1..48a26d37922 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -386,7 +386,6 @@ extern unsigned long cpuidle_disable; enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF}; extern int powersave_nap; /* set if nap mode can be used in idle loop */ -void cpu_idle_wait(void); #ifdef CONFIG_PSERIES_IDLE extern void update_smt_snooze_delay(int snooze); diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c index 04d79093d7a..2099d9a879e 100644 --- a/arch/powerpc/kernel/idle.c +++ b/arch/powerpc/kernel/idle.c @@ -113,25 +113,6 @@ void cpu_idle(void) } } -static void do_nothing(void *unused) -{ -} - -/* - * cpu_idle_wait - Used to ensure that all the CPUs come out of the old - * idle loop and start using the new idle loop. - * Required while changing idle handler on SMP systems. - * Caller must have changed idle handler to the new value before the call. - * This window may be larger on shared systems. - */ -void cpu_idle_wait(void) -{ - smp_mb(); - /* kick all the CPUs so that they exit out of pm_idle */ - smp_call_function(do_nothing, NULL, 1); -} -EXPORT_SYMBOL_GPL(cpu_idle_wait); - int powersave_nap; #ifdef CONFIG_SYSCTL -- cgit v1.2.3-70-g09d2