summaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2009-04-24 00:59:43 +0200
committerLen Brown <len.brown@intel.com>2009-04-24 03:51:51 +0200
commitf461ddea0af8b98e2b7940eba9c693b0ee44d64a (patch)
tree77a1b7eb4406ac1e96aaddb8ded9ea517b5a869a /drivers/acpi
parentLinux 2.6.30-rc3 (diff)
downloadlinux-f461ddea0af8b98e2b7940eba9c693b0ee44d64a.tar.xz
linux-f461ddea0af8b98e2b7940eba9c693b0ee44d64a.zip
ACPI/hpet: prevent boot hang when hpet=force used on ICH-4M
Linux tells ICH4 users that they can (manually) invoke "hpet=force" to enable the undocumented ICH-4M HPET. The HPET becomes available for both clocksource and clockevents. But as of ff69f2bba67bd45514923aaedbf40fe351787c59 (acpi: fix of pmtimer overflow that make Cx states time incorrect) the HPET may be used via clocksource for idle accounting, and hpet=force on an ICH4 box hangs boot. It turns out that touching the MMIO HPET withing the ARB_DIS part of C3 will hang the hardware. The fix is to simply move the timer access outside the ARB_DIS region. This is a no-op on modern hardware because ARB_DIS is no longer used. http://bugzilla.kernel.org/show_bug.cgi?id=13087 Acked-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/processor_idle.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 6fe121434ffb..ea23c64bd766 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -955,6 +955,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
*/
acpi_state_timer_broadcast(pr, cx, 1);
+ kt1 = ktime_get_real();
/*
* disable bus master
* bm_check implies we need ARB_DIS
@@ -976,10 +977,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
ACPI_FLUSH_CPU_CACHE();
}
- kt1 = ktime_get_real();
acpi_idle_do_entry(cx);
- kt2 = ktime_get_real();
- idle_time = ktime_to_us(ktime_sub(kt2, kt1));
/* Re-enable bus master arbitration */
if (pr->flags.bm_check && pr->flags.bm_control) {
@@ -988,6 +986,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
c3_cpu_count--;
spin_unlock(&c3_lock);
}
+ kt2 = ktime_get_real();
+ idle_time = ktime_to_us(ktime_sub(kt2, kt1));
#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86)
/* TSC could halt in idle, so notify users */