diff options
author | Liu, Jinsong <jinsong.liu@intel.com> | 2011-03-10 18:37:40 +0000 |
---|---|---|
committer | Liu, Jinsong <jinsong.liu@intel.com> | 2011-03-10 18:37:40 +0000 |
commit | ae2d7af49d7c71267f47614150e1d42315ea6607 (patch) | |
tree | 12889dc4f4055ded7e201d12cae332ff3a685ca1 | |
parent | 8fa00387409c3fa1faadba90d723f547abf17bf8 (diff) | |
download | xen-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.c | 44 |
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 */ |