aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorPallipadi, Venkatesh <venkatesh.pallipadi@intel.com>2010-02-10 13:35:31 -0500
committerLen Brown <len.brown@intel.com>2010-02-22 13:10:14 -0500
commitd306ebc28649b89877a22158fe0076f06cc46f60 (patch)
tree9a054d9a01889acca64bf018ed1e4778db0d5e19 /drivers/acpi
parent627fa177a1502ad24390d945851209ac022f3a36 (diff)
ACPI: Be in TS_POLLING state during mwait based C-state entry
ACPI deep C-state entry had a long standing bug/missing feature, wherein we were sending resched IPIs when an idle CPU is in mwait based deep C-state. Only mwait based C1 was using the write to the monitored address to wake up mwait'ing CPU. This patch changes the code to retain TS_POLLING bit if we are entering an mwait based deep C-state. The patch has been verified to reduce the number of resched IPIs in general and also improves the performance/power on workloads with low system utilization (i.e., when mwait based deep C-states are being used). Fixes "netperf ~50% regression with 2.6.33-rc1, bisect to 1b9508f" http://marc.info/?l=linux-kernel&m=126441481427331&w=4 Reported-by: Lin Ming <ming.m.lin@intel.com> Tested-by: Alex Shi <alex.shi@intel.com> Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/processor_idle.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index e88e8ae04fdb..cc978a8c00b7 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -880,12 +880,14 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
880 return(acpi_idle_enter_c1(dev, state)); 880 return(acpi_idle_enter_c1(dev, state));
881 881
882 local_irq_disable(); 882 local_irq_disable();
883 current_thread_info()->status &= ~TS_POLLING; 883 if (cx->entry_method != ACPI_CSTATE_FFH) {
884 /* 884 current_thread_info()->status &= ~TS_POLLING;
885 * TS_POLLING-cleared state must be visible before we test 885 /*
886 * NEED_RESCHED: 886 * TS_POLLING-cleared state must be visible before we test
887 */ 887 * NEED_RESCHED:
888 smp_mb(); 888 */
889 smp_mb();
890 }
889 891
890 if (unlikely(need_resched())) { 892 if (unlikely(need_resched())) {
891 current_thread_info()->status |= TS_POLLING; 893 current_thread_info()->status |= TS_POLLING;
@@ -965,12 +967,14 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
965 } 967 }
966 968
967 local_irq_disable(); 969 local_irq_disable();
968 current_thread_info()->status &= ~TS_POLLING; 970 if (cx->entry_method != ACPI_CSTATE_FFH) {
969 /* 971 current_thread_info()->status &= ~TS_POLLING;
970 * TS_POLLING-cleared state must be visible before we test 972 /*
971 * NEED_RESCHED: 973 * TS_POLLING-cleared state must be visible before we test
972 */ 974 * NEED_RESCHED:
973 smp_mb(); 975 */
976 smp_mb();
977 }
974 978
975 if (unlikely(need_resched())) { 979 if (unlikely(need_resched())) {
976 current_thread_info()->status |= TS_POLLING; 980 current_thread_info()->status |= TS_POLLING;