Skip to content

Commit 30c7e5b

Browse files
Peter ZijlstraKAGA-KOKO
authored andcommitted
x86/tsc: Allow TSC calibration without PIT
Zhang Rui reported that a Surface Pro 4 will fail to boot with lapic=notscdeadline. Part of the problem is that that machine doesn't have a PIT. If, for some reason, the TSC init has to fall back to TSC calibration, it relies on the PIT to be present. Allow TSC calibration to reliably fall back to HPET. The below results in an accurate TSC measurement when forced on a IVB: tsc: Unable to calibrate against PIT tsc: No reference (HPET/PMTIMER) available tsc: Unable to calibrate against PIT tsc: using HPET reference calibration tsc: Detected 2792.451 MHz processor Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Cc: [email protected] Cc: [email protected] Link: https://lkml.kernel.org/r/[email protected]
1 parent 4b5b212 commit 30c7e5b

File tree

2 files changed

+23
-0
lines changed

2 files changed

+23
-0
lines changed

arch/x86/include/asm/i8259.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ struct legacy_pic {
6969
extern struct legacy_pic *legacy_pic;
7070
extern struct legacy_pic null_legacy_pic;
7171

72+
static inline bool has_legacy_pic(void)
73+
{
74+
return legacy_pic != &null_legacy_pic;
75+
}
76+
7277
static inline int nr_legacy_irqs(void)
7378
{
7479
return legacy_pic->nr_legacy_irqs;

arch/x86/kernel/tsc.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <asm/geode.h>
2626
#include <asm/apic.h>
2727
#include <asm/intel-family.h>
28+
#include <asm/i8259.h>
2829

2930
unsigned int __read_mostly cpu_khz; /* TSC clocks / usec, not used here */
3031
EXPORT_SYMBOL(cpu_khz);
@@ -363,6 +364,20 @@ static unsigned long pit_calibrate_tsc(u32 latch, unsigned long ms, int loopmin)
363364
unsigned long tscmin, tscmax;
364365
int pitcnt;
365366

367+
if (!has_legacy_pic()) {
368+
/*
369+
* Relies on tsc_early_delay_calibrate() to have given us semi
370+
* usable udelay(), wait for the same 50ms we would have with
371+
* the PIT loop below.
372+
*/
373+
udelay(10 * USEC_PER_MSEC);
374+
udelay(10 * USEC_PER_MSEC);
375+
udelay(10 * USEC_PER_MSEC);
376+
udelay(10 * USEC_PER_MSEC);
377+
udelay(10 * USEC_PER_MSEC);
378+
return ULONG_MAX;
379+
}
380+
366381
/* Set the Gate high, disable speaker */
367382
outb((inb(0x61) & ~0x02) | 0x01, 0x61);
368383

@@ -487,6 +502,9 @@ static unsigned long quick_pit_calibrate(void)
487502
u64 tsc, delta;
488503
unsigned long d1, d2;
489504

505+
if (!has_legacy_pic())
506+
return 0;
507+
490508
/* Set the Gate high, disable speaker */
491509
outb((inb(0x61) & ~0x02) | 0x01, 0x61);
492510

0 commit comments

Comments
 (0)