rpms/kernel/F-11 hpet-fixes.patch, NONE, 1.1 kernel.spec, 1.1571, 1.1572

Kyle McMartin kyle at fedoraproject.org
Fri Apr 24 14:31:38 UTC 2009


Author: kyle

Update of /cvs/pkgs/rpms/kernel/F-11
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv21701

Modified Files:
	kernel.spec 
Added Files:
	hpet-fixes.patch 
Log Message:
* Fri Apr 24 2009 Kyle McMartin <kyle at redhat.com>
- backport hpet fixes from 2.6.30-rc3.


hpet-fixes.patch:

--- NEW FILE hpet-fixes.patch ---
commit 7bad863035a98d0dd45ceb29c66b9c2ed90e595e
Author: Andreas Herrmann <andreas.herrmann3 at amd.com>
Date:   Sat Feb 21 00:16:35 2009 +0100

    x86: hpet: stop HPET_COUNTER when programming periodic mode
    
    Impact: fix system hang on some systems operating with HZ_1000
    
    On a system that stalled with HZ_1000, the first value written to
    T0_CMP (when the main counter was not stopped) did not trigger an
    interrupt. Instead after the main counter wrapped around (after
    several minutes) an interrupt was triggered and afterwards the
    periodic interrupt took effect.
    
    This can be fixed by implementing HPET spec recommendation for
    programming the periodic mode (i.e. stopping the main counter).
    
    Signed-off-by: Andreas Herrmann <andreas.herrmann3 at amd.com>
    Cc: Mark Hounschell <markh at compro.net>
    Cc: Borislav Petkov <borislav.petkov at amd.com>
    Signed-off-by: Ingo Molnar <mingo at elte.hu>

commit 91773c91e460964100bc2534a33569f71ea9bdd2
Author: Andreas Herrmann <andreas.herrmann3 at amd.com>
Date:   Sat Feb 21 00:09:47 2009 +0100

    x86: hpet: print HPET registers during setup (if hpet=verbose is used)
    
    Signed-off-by: Andreas Herrmann <andreas.herrmann3 at amd.com>
    Cc: Mark Hounschell <markh at compro.net>
    Cc: Borislav Petkov <borislav.petkov at amd.com>
    Signed-off-by: Ingo Molnar <mingo at elte.hu>

commit 8c10fa6d34f8414c7c4efcdb39323150bdac82bc
Author: Andreas Herrmann <andreas.herrmann3 at amd.com>
Date:   Sat Feb 21 00:10:44 2009 +0100

    x86: hpet: provide separate functions to stop and start the counter
    
    By splitting up existing hpet_start_counter function.
    
    Signed-off-by: Andreas Herrmann <andreas.herrmann3 at amd.com>
    Cc: Mark Hounschell <markh at compro.net>
    Cc: Borislav Petkov <borislav.petkov at amd.com>
    Signed-off-by: Ingo Molnar <mingo at elte.hu>

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 54f21a5..46d11a9 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -492,10 +492,12 @@ and is between 256 and 4096 characters. It is defined in the file
 			Default: 64
 
 	hpet=		[X86-32,HPET] option to control HPET usage
-			Format: { enable (default) | disable | force }
+			Format: { enable (default) | disable | force |
+				verbose }
 			disable: disable HPET and use PIT instead
 			force: allow force enabled of undocumented chips (ICH4,
 			VIA, nVidia)
+			verbose: show contents of HPET registers during setup
 
 	com20020=	[HW,NET] ARCnet - COM20020 chipset
 			Format:
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index a00545f..648b3a2 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -80,6 +80,7 @@ static inline void hpet_clear_mapping(void)
  */
 static int boot_hpet_disable;
 int hpet_force_user;
+static int hpet_verbose;
 
 static int __init hpet_setup(char *str)
 {
@@ -88,6 +89,8 @@ static int __init hpet_setup(char *str)
 			boot_hpet_disable = 1;
 		if (!strncmp("force", str, 5))
 			hpet_force_user = 1;
+		if (!strncmp("verbose", str, 7))
+			hpet_verbose = 1;
 	}
 	return 1;
 }
@@ -119,6 +122,43 @@ int is_hpet_enabled(void)
 }
 EXPORT_SYMBOL_GPL(is_hpet_enabled);
 
+static void _hpet_print_config(const char *function, int line)
+{
+	u32 i, timers, l, h;
+	printk(KERN_INFO "hpet: %s(%d):\n", function, line);
+	l = hpet_readl(HPET_ID);
+	h = hpet_readl(HPET_PERIOD);
+	timers = ((l & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
+	printk(KERN_INFO "hpet: ID: 0x%x, PERIOD: 0x%x\n", l, h);
+	l = hpet_readl(HPET_CFG);
+	h = hpet_readl(HPET_STATUS);
+	printk(KERN_INFO "hpet: CFG: 0x%x, STATUS: 0x%x\n", l, h);
+	l = hpet_readl(HPET_COUNTER);
+	h = hpet_readl(HPET_COUNTER+4);
+	printk(KERN_INFO "hpet: COUNTER_l: 0x%x, COUNTER_h: 0x%x\n", l, h);
+
+	for (i = 0; i < timers; i++) {
+		l = hpet_readl(HPET_Tn_CFG(i));
+		h = hpet_readl(HPET_Tn_CFG(i)+4);
+		printk(KERN_INFO "hpet: T%d: CFG_l: 0x%x, CFG_h: 0x%x\n",
+		       i, l, h);
+		l = hpet_readl(HPET_Tn_CMP(i));
+		h = hpet_readl(HPET_Tn_CMP(i)+4);
+		printk(KERN_INFO "hpet: T%d: CMP_l: 0x%x, CMP_h: 0x%x\n",
+		       i, l, h);
+		l = hpet_readl(HPET_Tn_ROUTE(i));
+		h = hpet_readl(HPET_Tn_ROUTE(i)+4);
+		printk(KERN_INFO "hpet: T%d ROUTE_l: 0x%x, ROUTE_h: 0x%x\n",
+		       i, l, h);
+	}
+}
+
+#define hpet_print_config()					\
+do {								\
+	if (hpet_verbose)					\
+		_hpet_print_config(__FUNCTION__, __LINE__);	\
+} while (0)
+
 /*
  * When the hpet driver (/dev/hpet) is enabled, we need to reserve
  * timer 0 and timer 1 in case of RTC emulation.
@@ -191,27 +231,37 @@ static struct clock_event_device hpet_clockevent = {
 	.rating		= 50,
 };
 
-static void hpet_start_counter(void)
+static void hpet_stop_counter(void)
 {
 	unsigned long cfg = hpet_readl(HPET_CFG);
-
 	cfg &= ~HPET_CFG_ENABLE;
 	hpet_writel(cfg, HPET_CFG);
 	hpet_writel(0, HPET_COUNTER);
 	hpet_writel(0, HPET_COUNTER + 4);
+}
+
+static void hpet_start_counter(void)
+{
+	unsigned long cfg = hpet_readl(HPET_CFG);
 	cfg |= HPET_CFG_ENABLE;
 	hpet_writel(cfg, HPET_CFG);
 }
 
+static void hpet_restart_counter(void)
+{
+	hpet_stop_counter();
+	hpet_start_counter();
+}
+
 static void hpet_resume_device(void)
 {
 	force_hpet_resume();
 }
 
-static void hpet_restart_counter(void)
+static void hpet_resume_counter(void)
 {
 	hpet_resume_device();
-	hpet_start_counter();
+	hpet_restart_counter();
 }
 
 static void hpet_enable_legacy_int(void)
@@ -259,29 +309,23 @@ static int hpet_setup_msi_irq(unsigned int irq);
 static void hpet_set_mode(enum clock_event_mode mode,
 			  struct clock_event_device *evt, int timer)
 {
-	unsigned long cfg, cmp, now;
+	unsigned long cfg;
 	uint64_t delta;
 
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
+		hpet_stop_counter();
 		delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * evt->mult;
 		delta >>= evt->shift;
-		now = hpet_readl(HPET_COUNTER);
-		cmp = now + (unsigned long) delta;
 		cfg = hpet_readl(HPET_Tn_CFG(timer));
 		/* Make sure we use edge triggered interrupts */
 		cfg &= ~HPET_TN_LEVEL;
 		cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
 		       HPET_TN_SETVAL | HPET_TN_32BIT;
 		hpet_writel(cfg, HPET_Tn_CFG(timer));
-		/*
-		 * The first write after writing TN_SETVAL to the
-		 * config register sets the counter value, the second
-		 * write sets the period.
-		 */
-		hpet_writel(cmp, HPET_Tn_CMP(timer));
-		udelay(1);
 		hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer));
+		hpet_start_counter();
+		hpet_print_config();
 		break;
 
 	case CLOCK_EVT_MODE_ONESHOT:
@@ -308,6 +352,7 @@ static void hpet_set_mode(enum clock_event_mode mode,
 			irq_set_affinity(hdev->irq, cpumask_of(hdev->cpu));
 			enable_irq(hdev->irq);
 		}
+		hpet_print_config();
 		break;
 	}
 }
@@ -526,6 +571,7 @@ static void hpet_msi_capability_lookup(unsigned int start_timer)
 
 	num_timers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT);
 	num_timers++; /* Value read out starts from 0 */
+	hpet_print_config();
 
 	hpet_devs = kzalloc(sizeof(struct hpet_dev) * num_timers, GFP_KERNEL);
 	if (!hpet_devs)
@@ -695,7 +741,7 @@ static struct clocksource clocksource_hpet = {
 	.mask		= HPET_MASK,
 	.shift		= HPET_SHIFT,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-	.resume		= hpet_restart_counter,
+	.resume		= hpet_resume_counter,
 #ifdef CONFIG_X86_64
 	.vread		= vread_hpet,
 #endif
@@ -707,7 +753,7 @@ static int hpet_clocksource_register(void)
 	cycle_t t1;
 
 	/* Start the counter */
-	hpet_start_counter();
+	hpet_restart_counter();
 
 	/* Verify whether hpet counter works */
 	t1 = read_hpet();
@@ -793,6 +839,7 @@ int __init hpet_enable(void)
 	 * information and the number of channels
 	 */
 	id = hpet_readl(HPET_ID);
+	hpet_print_config();
 
 #ifdef CONFIG_HPET_EMULATE_RTC
 	/*
@@ -845,6 +892,7 @@ static __init int hpet_late_init(void)
 		return -ENODEV;
 
 	hpet_reserve_platform_timers(hpet_readl(HPET_ID));
+	hpet_print_config();
 
 	for_each_online_cpu(cpu) {
 		hpet_cpuhp_notify(NULL, CPU_ONLINE, (void *)(long)cpu);


Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-11/kernel.spec,v
retrieving revision 1.1571
retrieving revision 1.1572
diff -u -r1.1571 -r1.1572
--- kernel.spec	24 Apr 2009 04:34:34 -0000	1.1571
+++ kernel.spec	24 Apr 2009 14:31:07 -0000	1.1572
@@ -737,6 +737,8 @@
 Patch7004: linux-2.6-posix-timers-fix-rlimit_cpu-setitimer.patch
 Patch7005: linux-2.6-i2c-fix-bit-algorithm-timeout.patch
 
+Patch9000: hpet-fixes.patch
+
 Patch9001: revert-fix-modules_install-via-nfs.patch
 
 Patch9002: cpufreq-add-atom-to-p4-clockmod.patch
@@ -1381,6 +1383,8 @@
 ApplyPatch linux-2.6-posix-timers-fix-rlimit_cpu-setitimer.patch
 ApplyPatch linux-2.6-i2c-fix-bit-algorithm-timeout.patch
 
+ApplyPatch hpet-fixes.patch
+
 # revert 8b249b6856f16f09b0e5b79ce5f4d435e439b9d6
 ApplyPatch revert-fix-modules_install-via-nfs.patch
 
@@ -1984,6 +1988,9 @@
 # and build.
 
 %changelog
+* Fri Apr 24 2009 Kyle McMartin <kyle at redhat.com>
+- backport hpet fixes from 2.6.30-rc3.
+
 * Fri Apr 24 2009 Dave Airlie <airlied at redhat.com> 2.6.29.1-109
 - linux-2.6-i2c-fix-bit-algorithm-timeout.patch - fix i2c EDID timeout
 




More information about the fedora-extras-commits mailing list