summary refs log tree commit diff
path: root/drivers
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2009-04-23 18:59:43 -0400
committerLen Brown <len.brown@intel.com>2009-04-23 21:51:51 -0400
commitf461ddea0af8b98e2b7940eba9c693b0ee44d64a (patch)
tree77a1b7eb4406ac1e96aaddb8ded9ea517b5a869a /drivers
parent091069740304c979f957ceacec39c461d0192158 (diff)
downloadlinux-f461ddea0af8b98e2b7940eba9c693b0ee44d64a.tar.gz
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')
-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 */