diff options
author | Pallipadi, Venkatesh <venkatesh.pallipadi@intel.com> | 2010-02-10 13:35:31 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2010-02-22 13:10:14 -0500 |
commit | d306ebc28649b89877a22158fe0076f06cc46f60 (patch) | |
tree | 9a054d9a01889acca64bf018ed1e4778db0d5e19 | |
parent | 627fa177a1502ad24390d945851209ac022f3a36 (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>
-rw-r--r-- | drivers/acpi/processor_idle.c | 28 |
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; |