diff options
author | Len Brown <len.brown@intel.com> | 2009-04-23 18:59:43 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-04-23 21:51:51 -0400 |
commit | f461ddea0af8b98e2b7940eba9c693b0ee44d64a (patch) | |
tree | 77a1b7eb4406ac1e96aaddb8ded9ea517b5a869a /drivers/acpi | |
parent | 091069740304c979f957ceacec39c461d0192158 (diff) |
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.c | 6 |
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, | |||
955 | */ | 955 | */ |
956 | acpi_state_timer_broadcast(pr, cx, 1); | 956 | acpi_state_timer_broadcast(pr, cx, 1); |
957 | 957 | ||
958 | kt1 = ktime_get_real(); | ||
958 | /* | 959 | /* |
959 | * disable bus master | 960 | * disable bus master |
960 | * bm_check implies we need ARB_DIS | 961 | * bm_check implies we need ARB_DIS |
@@ -976,10 +977,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
976 | ACPI_FLUSH_CPU_CACHE(); | 977 | ACPI_FLUSH_CPU_CACHE(); |
977 | } | 978 | } |
978 | 979 | ||
979 | kt1 = ktime_get_real(); | ||
980 | acpi_idle_do_entry(cx); | 980 | acpi_idle_do_entry(cx); |
981 | kt2 = ktime_get_real(); | ||
982 | idle_time = ktime_to_us(ktime_sub(kt2, kt1)); | ||
983 | 981 | ||
984 | /* Re-enable bus master arbitration */ | 982 | /* Re-enable bus master arbitration */ |
985 | if (pr->flags.bm_check && pr->flags.bm_control) { | 983 | if (pr->flags.bm_check && pr->flags.bm_control) { |
@@ -988,6 +986,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
988 | c3_cpu_count--; | 986 | c3_cpu_count--; |
989 | spin_unlock(&c3_lock); | 987 | spin_unlock(&c3_lock); |
990 | } | 988 | } |
989 | kt2 = ktime_get_real(); | ||
990 | idle_time = ktime_to_us(ktime_sub(kt2, kt1)); | ||
991 | 991 | ||
992 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) | 992 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) |
993 | /* TSC could halt in idle, so notify users */ | 993 | /* TSC could halt in idle, so notify users */ |