From: Linus Torvalds <torvalds@linux-foundation.org>
To: Jesper Krogh <jesper@krogh.cc>
Cc: john stultz <johnstul@us.ibm.com>,
Thomas Gleixner <tglx@linutronix.de>,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
Len Brown <len.brown@intel.com>, Ingo Molnar <mingo@elte.hu>
Subject: Re: Linux 2.6.29-rc6
Date: Mon, 16 Mar 2009 12:32:06 -0700 (PDT) [thread overview]
Message-ID: <alpine.LFD.2.00.0903161225210.3675@localhost.localdomain> (raw)
In-Reply-To: <49BEA1AD.1090901@krogh.cc>
On Mon, 16 Mar 2009, Jesper Krogh wrote:
>
> you were right. It works. No resets so far.
Goodie.
Here's a slightly cleaned-up patch that removes the debug messages, and
also re-organizes the code a bit so that it actually uses the "better than
500 ppm" as the way to decide when to stop calibrating.
Why?
I tested the 500 ppm check on some slower machines, and the old algorithm
of just waiting for 15ms actually failed that 500 ppm test. It was _very_
close - 16ms was enough - but it convinced me that the logic was too damn
fragile.
I also think I know why John reported this:
> Ingo, Thomas: On the hardware I'm testing the fast-pit calibration only
> triggers probably 80-90% of the time. About 10-20% of the time, the
> initial check to pit_expect_msb(0xff) fails (count=0), so we may need to
> look more at this approach.
and the reason is that when we re-program the PIT, it will actually take
until the next timer edge (the incoming 1.1MHz timer) for the new values
to take effect. So before the first call to pit_expect_msb(), we should
make sure to delay for at least one PIT cycle. The simplest way to do that
is to simply read the PIT latch once, it will take about 2us.
So this patch fixes that too.
John, does that make the PIT calibration work reliably on your machine?
The patch looks bigger than it is: most of the noise is just
re-indentation and some trivial re-organizing.
Linus
---
arch/x86/kernel/tsc.c | 110 +++++++++++++++++++++++++++++--------------------
1 files changed, 65 insertions(+), 45 deletions(-)
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 599e581..d5cebb5 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -273,30 +273,43 @@ static unsigned long pit_calibrate_tsc(u32 latch, unsigned long ms, int loopmin)
* use the TSC value at the transitions to calculate a pretty
* good value for the TSC frequencty.
*/
-static inline int pit_expect_msb(unsigned char val)
+static inline int pit_expect_msb(unsigned char val, u64 *tscp, unsigned long *deltap)
{
- int count = 0;
+ int count;
+ u64 tsc = 0;
for (count = 0; count < 50000; count++) {
/* Ignore LSB */
inb(0x42);
if (inb(0x42) != val)
break;
+ tsc = get_cycles();
}
- return count > 50;
+ *deltap = get_cycles() - tsc;
+ *tscp = tsc;
+
+ /*
+ * We require _some_ success, but the quality control
+ * will be based on the error terms on the TSC values.
+ */
+ return count > 5;
}
/*
- * How many MSB values do we want to see? We aim for a
- * 15ms calibration, which assuming a 2us counter read
- * error should give us roughly 150 ppm precision for
- * the calibration.
+ * How many MSB values do we want to see? We aim for
+ * a maximum error rate of 500ppm (in practice the
+ * real error is much smaller), but refuse to spend
+ * more than 25ms on it.
*/
-#define QUICK_PIT_MS 15
-#define QUICK_PIT_ITERATIONS (QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256)
+#define MAX_QUICK_PIT_MS 25
+#define MAX_QUICK_PIT_ITERATIONS (MAX_QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256)
static unsigned long quick_pit_calibrate(void)
{
+ int i;
+ u64 tsc, delta;
+ unsigned long d1, d2;
+
/* Set the Gate high, disable speaker */
outb((inb(0x61) & ~0x02) | 0x01, 0x61);
@@ -315,45 +328,52 @@ static unsigned long quick_pit_calibrate(void)
outb(0xff, 0x42);
outb(0xff, 0x42);
- if (pit_expect_msb(0xff)) {
- int i;
- u64 t1, t2, delta;
- unsigned char expect = 0xfe;
-
- t1 = get_cycles();
- for (i = 0; i < QUICK_PIT_ITERATIONS; i++, expect--) {
- if (!pit_expect_msb(expect))
- goto failed;
+ /*
+ * The PIT starts counting at the next edge, so we
+ * need to delay for a microsecond. The easiest way
+ * to do that is to just read back the 16-bit counter
+ * once from the PIT.
+ */
+ inb(0x42);
+ inb(0x42);
+
+ if (pit_expect_msb(0xff, &tsc, &d1)) {
+ for (i = 1; i <= MAX_QUICK_PIT_ITERATIONS; i++) {
+ if (!pit_expect_msb(0xff-i, &delta, &d2))
+ break;
+
+ /*
+ * Iterate until the error is less than 500 ppm
+ */
+ delta -= tsc;
+ if (d1+d2 < delta >> 11)
+ goto success;
}
- t2 = get_cycles();
-
- /*
- * Make sure we can rely on the second TSC timestamp:
- */
- if (!pit_expect_msb(expect))
- goto failed;
-
- /*
- * Ok, if we get here, then we've seen the
- * MSB of the PIT decrement QUICK_PIT_ITERATIONS
- * times, and each MSB had many hits, so we never
- * had any sudden jumps.
- *
- * As a result, we can depend on there not being
- * any odd delays anywhere, and the TSC reads are
- * reliable.
- *
- * kHz = ticks / time-in-seconds / 1000;
- * kHz = (t2 - t1) / (QPI * 256 / PIT_TICK_RATE) / 1000
- * kHz = ((t2 - t1) * PIT_TICK_RATE) / (QPI * 256 * 1000)
- */
- delta = (t2 - t1)*PIT_TICK_RATE;
- do_div(delta, QUICK_PIT_ITERATIONS*256*1000);
- printk("Fast TSC calibration using PIT\n");
- return delta;
}
-failed:
+ printk("Fast TSC calibration failed\n");
return 0;
+
+success:
+ /*
+ * Ok, if we get here, then we've seen the
+ * MSB of the PIT decrement 'i' times, and the
+ * error has shrunk to less than 500 ppm.
+ *
+ * As a result, we can depend on there not being
+ * any odd delays anywhere, and the TSC reads are
+ * reliable (within the error). We also adjust the
+ * delta to the middle of the error bars, just
+ * because it looks nicer.
+ *
+ * kHz = ticks / time-in-seconds / 1000;
+ * kHz = (t2 - t1) / (I * 256 / PIT_TICK_RATE) / 1000
+ * kHz = ((t2 - t1) * PIT_TICK_RATE) / (I * 256 * 1000)
+ */
+ delta += (long)(d2 - d1)/2;
+ delta *= PIT_TICK_RATE;
+ do_div(delta, i*256*1000);
+ printk("Fast TSC calibration using PIT\n");
+ return delta;
}
/**
next prev parent reply other threads:[~2009-03-16 19:36 UTC|newest]
Thread overview: 81+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-02-23 4:31 Linus Torvalds
2009-02-23 14:07 ` Linux 2.6.29-rc6 - Fix oops in i915_gem_retire_requests Karsten Wiese
2009-02-26 11:15 ` Linux 2.6.29-rc6 Jesper Krogh
2009-02-26 17:17 ` MTD_CK804XROM warning (Was: Linux 2.6.29-rc6) Marcin Slusarz
2009-02-26 17:53 ` Linux 2.6.29-rc6 Linus Torvalds
2009-02-26 19:22 ` David Woodhouse
2009-02-26 19:31 ` Jesper Krogh
2009-02-26 19:36 ` David Woodhouse
2009-02-26 19:46 ` Jesper Krogh
2009-02-26 19:49 ` David Woodhouse
2009-02-26 20:53 ` Carl-Daniel Hailfinger
2009-02-26 20:32 ` Linus Torvalds
2009-02-26 19:55 ` Jesper Krogh
2009-02-26 20:33 ` Linus Torvalds
2009-02-26 20:43 ` Jesper Krogh
2009-02-26 21:19 ` john stultz
2009-02-26 21:35 ` Jesper Krogh
2009-02-26 21:46 ` john stultz
2009-02-26 21:54 ` Thomas Gleixner
2009-02-26 22:04 ` Jesper Krogh
2009-02-27 6:30 ` Jesper Krogh
2009-03-01 13:51 ` Jesper Krogh
2009-02-26 21:49 ` Linus Torvalds
2009-03-01 15:04 ` Jesper Krogh
2009-02-26 21:54 ` john stultz
2009-02-26 22:06 ` Thomas Gleixner
2009-02-26 22:24 ` Linus Torvalds
2009-02-26 22:31 ` Linus Torvalds
2009-02-26 22:31 ` john stultz
2009-02-26 22:40 ` Linus Torvalds
2009-02-26 22:59 ` john stultz
2009-02-27 7:33 ` Ingo Molnar
2009-02-27 20:50 ` john stultz
2009-02-27 6:47 ` Jesper Krogh
2009-02-27 20:35 ` john stultz
2009-03-01 20:13 ` Jesper Krogh
2009-03-02 9:53 ` Jesper Krogh
2009-03-02 21:27 ` john stultz
2009-03-03 6:04 ` Jesper Krogh
2009-03-03 19:53 ` john stultz
2009-03-03 20:19 ` Jesper Krogh
2009-03-03 22:22 ` john stultz
2009-03-04 15:30 ` Jesper Krogh
2009-03-04 18:36 ` Jesper Krogh
2009-03-04 18:57 ` John Stultz
2009-03-05 2:39 ` john stultz
2009-03-05 2:52 ` john stultz
2009-03-05 8:43 ` Ingo Molnar
2009-03-06 3:13 ` john stultz
2009-03-06 3:54 ` john stultz
2009-03-06 11:34 ` Ingo Molnar
2009-03-09 20:42 ` Jesper Krogh
2009-03-10 4:26 ` Linus Torvalds
2009-03-10 11:29 ` Thomas Gleixner
2009-03-10 19:42 ` Jesper Krogh
2009-03-10 22:22 ` Thomas Gleixner
2009-03-15 19:53 ` Jesper Krogh
2009-03-16 18:40 ` Jesper Krogh
2009-03-15 1:19 ` Linus Torvalds
2009-03-15 15:44 ` Jesper Krogh
2009-03-15 18:09 ` Linus Torvalds
2009-03-15 18:38 ` Jesper Krogh
2009-03-15 19:02 ` Linus Torvalds
2009-03-15 19:52 ` Jesper Krogh
2009-03-16 18:59 ` Jesper Krogh
2009-03-16 19:32 ` Linus Torvalds [this message]
2009-03-17 1:43 ` john stultz
2009-03-17 8:14 ` Ingo Molnar
2009-03-17 15:48 ` Linus Torvalds
2009-03-17 16:13 ` Ingo Molnar
2009-03-17 16:28 ` Linus Torvalds
2009-03-17 16:40 ` Ingo Molnar
2009-03-17 17:28 ` Olivier Galibert
2009-03-21 9:11 ` Jesper Krogh
2009-03-21 10:06 ` Ingo Molnar
2009-03-15 20:32 ` Linus Torvalds
2009-03-03 20:39 ` Jesper Krogh
2009-03-03 22:16 ` john stultz
2009-03-04 5:36 ` Jesper Krogh
2009-03-01 15:09 ` Jesper Krogh
2009-03-01 15:44 ` Linux 2.6.29-rc6 (clocksource) Sitsofe Wheeler
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=alpine.LFD.2.00.0903161225210.3675@localhost.localdomain \
--to=torvalds@linux-foundation.org \
--cc=jesper@krogh.cc \
--cc=johnstul@us.ibm.com \
--cc=len.brown@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome