public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] x86: dish of assorted hpet patches
@ 2009-02-20 23:07 Andreas Herrmann
  2009-02-20 23:09 ` [PATCH 1/3] x86: hpet: print HPET registers during setup (if hpet=verbose is used) Andreas Herrmann
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Andreas Herrmann @ 2009-02-20 23:07 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner
  Cc: linux-kernel, Mark Hounschell, Borislav Petkov


- to print HPET registers during setup,
- to fix a real issue with HZ_1000 kernels on an SB400 system
 (and to potentially fix a similar issue with SB600).

Tested on ICH7 and on AMD SB400, AMD SB600.


Please apply.

Thanks,
Andreas

-- 
Operating | Advanced Micro Devices GmbH
  System  | Karl-Hammerschmidt-Str. 34, 85609 Dornach b. München, Germany
 Research | Geschäftsführer: Jochen Polster, Thomas M. McCoy, Giuliano Meroni
  Center  | Sitz: Dornach, Gemeinde Aschheim, Landkreis München
  (OSRC)  | Registergericht München, HRB Nr. 43632



^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] x86: hpet: print HPET registers during setup (if hpet=verbose is used)
  2009-02-20 23:07 [PATCH 0/3] x86: dish of assorted hpet patches Andreas Herrmann
@ 2009-02-20 23:09 ` Andreas Herrmann
  2009-02-20 23:10 ` [PATCH 2/3] x86: hpet: provide separate functions to stop and start the counter Andreas Herrmann
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Andreas Herrmann @ 2009-02-20 23:09 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner
  Cc: linux-kernel, Mark Hounschell, Borislav Petkov


Impact: provide verbose HPET information

Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com>
---
 Documentation/kernel-parameters.txt |    4 ++-
 arch/x86/kernel/hpet.c              |   45 +++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+), 1 deletions(-)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index b182626..01379a8 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..84450b1 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.
@@ -282,6 +322,7 @@ static void hpet_set_mode(enum clock_event_mode mode,
 		hpet_writel(cmp, HPET_Tn_CMP(timer));
 		udelay(1);
 		hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer));
+		hpet_print_config();
 		break;
 
 	case CLOCK_EVT_MODE_ONESHOT:
@@ -308,6 +349,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 +568,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)
@@ -793,6 +836,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 +889,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);
-- 
1.6.1.3




^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] x86: hpet: provide separate functions to stop and start the counter
  2009-02-20 23:07 [PATCH 0/3] x86: dish of assorted hpet patches Andreas Herrmann
  2009-02-20 23:09 ` [PATCH 1/3] x86: hpet: print HPET registers during setup (if hpet=verbose is used) Andreas Herrmann
@ 2009-02-20 23:10 ` Andreas Herrmann
  2009-02-20 23:16 ` [PATCH 3/3] x86: hpet: stop HPET_COUNTER when programming periodic mode Andreas Herrmann
  2009-02-22 17:04 ` [PATCH 0/3] x86: dish of assorted hpet patches Ingo Molnar
  3 siblings, 0 replies; 6+ messages in thread
From: Andreas Herrmann @ 2009-02-20 23:10 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner
  Cc: linux-kernel, Mark Hounschell, Borislav Petkov


By splitting up existing hpet_start_counter function.

Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com>
---
 arch/x86/kernel/hpet.c |   22 ++++++++++++++++------
 1 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 84450b1..20acc6a 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -231,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)
@@ -738,7 +748,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
@@ -750,7 +760,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();
-- 
1.6.1.3




^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] x86: hpet: stop HPET_COUNTER when programming periodic mode
  2009-02-20 23:07 [PATCH 0/3] x86: dish of assorted hpet patches Andreas Herrmann
  2009-02-20 23:09 ` [PATCH 1/3] x86: hpet: print HPET registers during setup (if hpet=verbose is used) Andreas Herrmann
  2009-02-20 23:10 ` [PATCH 2/3] x86: hpet: provide separate functions to stop and start the counter Andreas Herrmann
@ 2009-02-20 23:16 ` Andreas Herrmann
  2009-02-24  6:25   ` Andreas Herrmann
  2009-02-22 17:04 ` [PATCH 0/3] x86: dish of assorted hpet patches Ingo Molnar
  3 siblings, 1 reply; 6+ messages in thread
From: Andreas Herrmann @ 2009-02-20 23:16 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner
  Cc: linux-kernel, Mark Hounschell, Borislav Petkov


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@amd.com>
---
 arch/x86/kernel/hpet.c |   13 +++----------
 1 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 20acc6a..46be008 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -309,29 +309,22 @@ 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;
 
-- 
1.6.1.3




^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/3] x86: dish of assorted hpet patches
  2009-02-20 23:07 [PATCH 0/3] x86: dish of assorted hpet patches Andreas Herrmann
                   ` (2 preceding siblings ...)
  2009-02-20 23:16 ` [PATCH 3/3] x86: hpet: stop HPET_COUNTER when programming periodic mode Andreas Herrmann
@ 2009-02-22 17:04 ` Ingo Molnar
  3 siblings, 0 replies; 6+ messages in thread
From: Ingo Molnar @ 2009-02-22 17:04 UTC (permalink / raw)
  To: Andreas Herrmann
  Cc: Thomas Gleixner, linux-kernel, Mark Hounschell, Borislav Petkov


* Andreas Herrmann <andreas.herrmann3@amd.com> wrote:

> - to print HPET registers during setup,
> - to fix a real issue with HZ_1000 kernels on an SB400 system
>  (and to potentially fix a similar issue with SB600).
> 
> Tested on ICH7 and on AMD SB400, AMD SB600.

applied to tip:timers/hpet, thanks Andreas!

Btw, maybe the HZ_1000 bugfix could be the fix for a weirdness 
i'm seeing very rarely on one of my testsystems:

[    8.850706] bus: 'pci': driver_probe_device: matched device 0000:04:00.0 with driver e1000e
[    8.850706] bus: 'pci': really_probe: probing driver e1000e with device 0000:04:00.0
[  177.308165] e1000e 0000:04:00.0: PCI INT A -> GSI 17 (level, low) -> IRQ 17
[  177.668182] e1000e 0000:04:00.0: setting latency timer to 64

there's almost 3 minutes between those lines printed, although 
it should have taken milliseconds!

	Ingo

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 3/3] x86: hpet: stop HPET_COUNTER when programming periodic mode
  2009-02-20 23:16 ` [PATCH 3/3] x86: hpet: stop HPET_COUNTER when programming periodic mode Andreas Herrmann
@ 2009-02-24  6:25   ` Andreas Herrmann
  0 siblings, 0 replies; 6+ messages in thread
From: Andreas Herrmann @ 2009-02-24  6:25 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner
  Cc: linux-kernel, Mark Hounschell, Borislav Petkov

On Sat, Feb 21, 2009 at 12:16:35AM +0100, Andreas Herrmann wrote:
> 
> 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).

Hi Ingo,

Please don't push this commit to Linus' tree.
Currently it's in tip:timers/hpet.

The patch didn't fix the problem that Mark Hounshell was reporting.

But first of all the patch might have side-effects as all hpet timers
that are affect when the main counter is stopped and reset. And
furthermore I have learned that there might have been hpet
implementations that require the second write (w/o HPET_TN_SETVAL bit)
to happen.

I am looking for a different solution.


Thanks,

Andreas



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2009-02-24  6:26 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-20 23:07 [PATCH 0/3] x86: dish of assorted hpet patches Andreas Herrmann
2009-02-20 23:09 ` [PATCH 1/3] x86: hpet: print HPET registers during setup (if hpet=verbose is used) Andreas Herrmann
2009-02-20 23:10 ` [PATCH 2/3] x86: hpet: provide separate functions to stop and start the counter Andreas Herrmann
2009-02-20 23:16 ` [PATCH 3/3] x86: hpet: stop HPET_COUNTER when programming periodic mode Andreas Herrmann
2009-02-24  6:25   ` Andreas Herrmann
2009-02-22 17:04 ` [PATCH 0/3] x86: dish of assorted hpet patches Ingo Molnar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox