Tested-by: Mike Galbraith <bitbucket@online.de>
Signed-off-by: Len Brown <len.brown@intel.com>
Acked-by: Mike Galbraith <bitbucket@online.de>
+Cc: <stable@vger.kernel.org> # 3.9+
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Ian Malone <ibmalone@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/345254a551eb5a6a866e048d7ab570fd2193aca4.1389763084.git.len.brown@intel.com
[ Ported to recent kernels. ]
+[ Mike: 3.10 backport ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Mike Galbraith <efault@gmx.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/process.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 49 insertions(+)
-diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h
-index a1410db38a1a..653dfa7662e1 100644
---- a/arch/x86/include/asm/mwait.h
-+++ b/arch/x86/include/asm/mwait.h
-@@ -30,6 +30,14 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
- :: "a" (eax), "c" (ecx));
- }
-
-+static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
-+{
-+ trace_hardirqs_on();
-+ /* "mwait %eax, %ecx;" */
-+ asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
-+ :: "a" (eax), "c" (ecx));
-+}
-+
- /*
- * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
- * which can obviate IPI to trigger checking of need_resched.
-diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
-index e127ddaa2d5a..da06f741d2a6 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
-@@ -24,6 +24,7 @@
- #include <asm/syscalls.h>
- #include <asm/idle.h>
- #include <asm/uaccess.h>
-+#include <asm/mwait.h>
- #include <asm/i387.h>
- #include <asm/fpu-internal.h>
- #include <asm/debugreg.h>
-@@ -398,6 +399,49 @@ static void amd_e400_idle(void)
+@@ -398,6 +398,52 @@ static void amd_e400_idle(void)
default_idle();
}
+
+static void mwait_idle(void)
+{
-+ if (!need_resched()) {
-+ if (this_cpu_has(X86_BUG_CLFLUSH_MONITOR))
++ if (!current_set_polling_and_test()) {
++ if (static_cpu_has(X86_FEATURE_CLFLUSH_MONITOR)) {
++ mb();
+ clflush((void *)¤t_thread_info()->flags);
++ mb();
++ }
+
+ __monitor((void *)¤t_thread_info()->flags, 0, 0);
-+ smp_mb();
+ if (!need_resched())
+ __sti_mwait(0, 0);
+ else
+ local_irq_enable();
+ } else
+ local_irq_enable();
++ __current_clr_polling();
+}
+
- void select_idle_routine(const struct cpuinfo_x86 *c)
+ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
-@@ -411,6 +455,9 @@ void select_idle_routine(const struct cpuinfo_x86 *c)
+@@ -411,6 +457,9 @@ void __cpuinit select_idle_routine(const
/* E400: APIC timer interrupt does not wake up CPU from C1e */
pr_info("using AMD E400 aware idle routine\n");
x86_idle = amd_e400_idle;