powerpc/cpuidle: Add cpu_idle_wait() to allow switching of idle routines
authorDeepthi Dharwar <deepthi@linux.vnet.ibm.com>
Wed, 30 Nov 2011 02:46:31 +0000 (02:46 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Thu, 8 Dec 2011 02:54:58 +0000 (13:54 +1100)
This patch provides cpu_idle_wait() routine for the powerpc
platform which is required by the cpuidle subsystem. This
routine is required to change the idle handler on SMP systems.
The equivalent routine for x86 is in arch/x86/kernel/process.c
but the powerpc implementation is different.

cpuidle_disable variable is to enable/disable cpuidle
framework if power_save option is set during the boot
time.

Signed-off-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
Signed-off-by: Trinabh Gupta <g.trinabh@gmail.com>
Signed-off-by: Arun R Bharadwaj <arun.r.bharadwaj@gmail.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/Kconfig
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/system.h
arch/powerpc/kernel/idle.c

index 7c93c7eb0e564898f946f08bb10dc53f16117e52..d66a47fde80c7e5b3e81add388c5e4bf1958d35b 100644 (file)
@@ -87,6 +87,10 @@ 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
index eb11a446720e0b4cbc2e2917e409781a4c43ad0f..811b7e744378cf7fcd9bfba6c71f305522239b68 100644 (file)
@@ -382,6 +382,8 @@ static inline unsigned long get_clean_sp(struct pt_regs *regs, int is_32)
 }
 #endif
 
+enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF};
+
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_POWERPC_PROCESSOR_H */
index e30a13d1ee76bd4947f922f81790d80baae5f57b..ff666803879944086d8a06dc5ec5f4359ecd83a3 100644 (file)
@@ -221,6 +221,7 @@ extern unsigned long klimit;
 extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
 
 extern int powersave_nap;      /* set if nap mode can be used in idle loop */
+void cpu_idle_wait(void);
 
 /*
  * Atomic exchange
index 39a2baa6ad58aec28a3c1d0782753569bbb51f6e..8574b0e81ff138648be7c3d398eae2bfe160c6f7 100644 (file)
 #define cpu_should_die()       0
 #endif
 
+unsigned long cpuidle_disable = IDLE_NO_OVERRIDE;
+EXPORT_SYMBOL(cpuidle_disable);
+
 static int __init powersave_off(char *arg)
 {
        ppc_md.power_save = NULL;
+       cpuidle_disable = IDLE_POWERSAVE_OFF;
        return 0;
 }
 __setup("powersave=off", powersave_off);
@@ -102,6 +106,29 @@ void cpu_idle(void)
        }
 }
 
+
+/*
+ * 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)
+{
+       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();
+}
+EXPORT_SYMBOL_GPL(cpu_idle_wait);
+
 int powersave_nap;
 
 #ifdef CONFIG_SYSCTL