summaryrefslogtreecommitdiff
path: root/drivers/acpi
diff options
context:
space:
mode:
authorPallipadi, Venkatesh <venkatesh.pallipadi@intel.com>2010-02-10 10:35:31 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-15 08:49:36 -0700
commitcc03dfc07cc4acf73b721ca9a57c6d4d2101ae49 (patch)
treeec44d3811ce467b9fa299cc653092bd87a5ee566 /drivers/acpi
parent35f32e94f5c5e392a1dcaf7af8bda33b85acc991 (diff)
ACPI: Be in TS_POLLING state during mwait based C-state entry
commit d306ebc28649b89877a22158fe0076f06cc46f60 upstream. 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> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
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 d9f78f6cbda3..c8f0797416a5 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -888,12 +888,14 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
return(acpi_idle_enter_c1(dev, state));
local_irq_disable();
- current_thread_info()->status &= ~TS_POLLING;
- /*
- * TS_POLLING-cleared state must be visible before we test
- * NEED_RESCHED:
- */
- smp_mb();
+ if (cx->entry_method != ACPI_CSTATE_FFH) {
+ current_thread_info()->status &= ~TS_POLLING;
+ /*
+ * TS_POLLING-cleared state must be visible before we test
+ * NEED_RESCHED:
+ */
+ smp_mb();
+ }
if (unlikely(need_resched())) {
current_thread_info()->status |= TS_POLLING;
@@ -973,12 +975,14 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
}
local_irq_disable();
- current_thread_info()->status &= ~TS_POLLING;
- /*
- * TS_POLLING-cleared state must be visible before we test
- * NEED_RESCHED:
- */
- smp_mb();
+ if (cx->entry_method != ACPI_CSTATE_FFH) {
+ current_thread_info()->status &= ~TS_POLLING;
+ /*
+ * TS_POLLING-cleared state must be visible before we test
+ * NEED_RESCHED:
+ */
+ smp_mb();
+ }
if (unlikely(need_resched())) {
current_thread_info()->status |= TS_POLLING;