diff options
author | Pallipadi, Venkatesh <venkatesh.pallipadi@intel.com> | 2010-02-10 10:35:31 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-04-01 15:55:53 -0700 |
commit | 54b663bdc94f94bf4d77566ec42d30d22b68ff8f (patch) | |
tree | efe5b156114738cdeb3138f68c4a9fdaf9eb6719 /drivers | |
parent | 354a8d03e60a13600346babc1a78ecce4075f917 (diff) | |
download | lwn-54b663bdc94f94bf4d77566ec42d30d22b68ff8f.tar.gz lwn-54b663bdc94f94bf4d77566ec42d30d22b68ff8f.zip |
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')
-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 66393d5c4c7c..f6d84694f17f 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -876,12 +876,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; @@ -961,12 +963,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; |