aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiu, Jinsong <jinsong.liu@intel.com>2011-03-10 18:37:40 +0000
committerLiu, Jinsong <jinsong.liu@intel.com>2011-03-10 18:37:40 +0000
commitae2d7af49d7c71267f47614150e1d42315ea6607 (patch)
tree12889dc4f4055ded7e201d12cae332ff3a685ca1
parent8fa00387409c3fa1faadba90d723f547abf17bf8 (diff)
downloadxen-ae2d7af49d7c71267f47614150e1d42315ea6607.tar.gz
xen-ae2d7af49d7c71267f47614150e1d42315ea6607.tar.bz2
xen-ae2d7af49d7c71267f47614150e1d42315ea6607.zip
x86: Fix cpuidle bug
Before invoking C3, bus master disable / flush cache should be the last step; After resume from C3, bus master enable should be the first step; Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> Acked-by: Wei Gang <gang.wei@intel.com> xen-unstable changeset: 23020:22cc047eb146 xen-unstable date: Thu Mar 10 18:35:32 2011 +0000
-rw-r--r--xen/arch/x86/acpi/cpu_idle.c44
1 files changed, 23 insertions, 21 deletions
diff --git a/xen/arch/x86/acpi/cpu_idle.c b/xen/arch/x86/acpi/cpu_idle.c
index bb2da8926b..7cbcceeb7a 100644
--- a/xen/arch/x86/acpi/cpu_idle.c
+++ b/xen/arch/x86/acpi/cpu_idle.c
@@ -457,6 +457,19 @@ static void acpi_processor_idle(void)
case ACPI_STATE_C3:
/*
+ * Before invoking C3, be aware that TSC/APIC timer may be
+ * stopped by H/W. Without carefully handling of TSC/APIC stop issues,
+ * deep C state can't work correctly.
+ */
+ /* preparing APIC stop */
+ lapic_timer_off();
+
+ /* Get start time (ticks) */
+ t1 = get_tick();
+ /* Trace cpu idle entry */
+ TRACE_4D(TRC_PM_IDLE_ENTRY, cx->idx, t1, exp, pred);
+
+ /*
* disable bus master
* bm_check implies we need ARB_DIS
* !bm_check implies we need cache flush
@@ -485,20 +498,18 @@ static void acpi_processor_idle(void)
ACPI_FLUSH_CPU_CACHE();
}
- /*
- * Before invoking C3, be aware that TSC/APIC timer may be
- * stopped by H/W. Without carefully handling of TSC/APIC stop issues,
- * deep C state can't work correctly.
- */
- /* preparing APIC stop */
- lapic_timer_off();
-
- /* Get start time (ticks) */
- t1 = get_tick();
- /* Trace cpu idle entry */
- TRACE_4D(TRC_PM_IDLE_ENTRY, cx->idx, t1, exp, pred);
/* Invoke C3 */
acpi_idle_do_entry(cx);
+
+ if ( power->flags.bm_check && power->flags.bm_control )
+ {
+ /* Enable bus master arbitration */
+ spin_lock(&c3_cpu_status.lock);
+ acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
+ c3_cpu_status.count--;
+ spin_unlock(&c3_cpu_status.lock);
+ }
+
/* Get end time (ticks) */
t2 = get_tick();
@@ -509,15 +520,6 @@ static void acpi_processor_idle(void)
TRACE_6D(TRC_PM_IDLE_EXIT, cx->idx, t2,
irq_traced[0], irq_traced[1], irq_traced[2], irq_traced[3]);
- if ( power->flags.bm_check && power->flags.bm_control )
- {
- /* Enable bus master arbitration */
- spin_lock(&c3_cpu_status.lock);
- if ( c3_cpu_status.count-- == num_online_cpus() )
- acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
- spin_unlock(&c3_cpu_status.lock);
- }
-
/* Re-enable interrupts */
local_irq_enable();
/* recovering APIC */