| From 7b8da0add152732a098077f5570e63abdd6e679b Mon Sep 17 00:00:00 2001 |
| From: H. Peter Anvin <hpa@linux.intel.com> |
| Date: Fri, 17 Sep 2010 17:06:46 -0700 |
| Subject: [PATCH] x86, hotplug: Move WBINVD back outside the play_dead loop |
| |
| commit a68e5c94f7d3dd64fef34dd5d97e365cae4bb42a upstream. |
| |
| On processors with hyperthreading, when only one thread is offlined |
| the other thread can cause a spurious wakeup on the idled thread. We |
| do not want to re-WBINVD when that happens. |
| |
| Ideally, we should simply skip WBINVD unless we're the last thread on |
| a particular core to shut down, but there might be similar issues |
| elsewhere in the system. |
| |
| Thus, revert to previous behavior of only WBINVD outside the loop. |
| Partly as a result, remove the mb()'s around it: they are not |
| necessary since wbinvd() is a serializing instruction, but they were |
| intended to make sure the compiler didn't do any funny loop |
| optimizations. |
| |
| Reported-by: Asit Mallick <asit.k.mallick@intel.com> |
| Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> |
| Cc: Arjan van de Ven <arjan@linux.kernel.org> |
| Cc: Len Brown <lenb@kernel.org> |
| Cc: Venkatesh Pallipadi <venki@google.com> |
| Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> |
| LKML-Reference: <tip-ea53069231f9317062910d6e772cca4ce93de8c8@git.kernel.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c |
| index d528e75..b283dbf 100644 |
| --- a/arch/x86/kernel/smpboot.c |
| +++ b/arch/x86/kernel/smpboot.c |
| @@ -1399,9 +1399,9 @@ static inline void mwait_play_dead(void) |
| (highest_subcstate - 1); |
| } |
| |
| + wbinvd(); |
| + |
| while (1) { |
| - mb(); |
| - wbinvd(); |
| __monitor(¤t_thread_info()->flags, 0, 0); |
| mb(); |
| __mwait(eax, 0); |
| @@ -1410,11 +1410,10 @@ static inline void mwait_play_dead(void) |
| |
| static inline void hlt_play_dead(void) |
| { |
| + if (current_cpu_data.x86 >= 4) |
| + wbinvd(); |
| + |
| while (1) { |
| - mb(); |
| - if (current_cpu_data.x86 >= 4) |
| - wbinvd(); |
| - mb(); |
| native_halt(); |
| } |
| } |
| -- |
| 1.7.4.4 |
| |