Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 19781
b: refs/heads/master
c: 0c3749c
h: refs/heads/master
i:
  19779: 4f8c1ec
v: v3
  • Loading branch information
Andi Kleen authored and Linus Torvalds committed Feb 5, 2006
1 parent be30629 commit 0ee6baa
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 099f318b8d97490e58c595eb1b6d3415da5ccc03
refs/heads/master: 0c3749c41f5eee0da36bbf92b2793338b4d8574f
5 changes: 5 additions & 0 deletions trunk/Documentation/x86_64/boot-options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ APICs
noapicmaintimer Don't do time keeping using the APIC timer.
Useful when this option was auto selected, but doesn't work.

apicpmtimer
Do APIC timer calibration using the pmtimer. Implies
apicmaintimer. Useful when your PIT timer is totally
broken.

Early Console

syntax: earlyprintk=vga
Expand Down
33 changes: 27 additions & 6 deletions trunk/arch/x86_64/kernel/apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

int apic_verbosity;
int apic_runs_main_timer;
int apic_calibrate_pmtmr __initdata;

int disable_apic_timer __initdata;

Expand Down Expand Up @@ -746,14 +747,27 @@ static int __init calibrate_APIC_clock(void)
__setup_APIC_LVTT(1000000000);

apic_start = apic_read(APIC_TMCCT);
rdtscl(tsc_start);

do {
#ifdef CONFIG_X86_PM_TIMER
if (apic_calibrate_pmtmr && pmtmr_ioport) {
pmtimer_wait(5000); /* 5ms wait */
apic = apic_read(APIC_TMCCT);
rdtscl(tsc);
} while ((tsc - tsc_start) < TICK_COUNT && (apic - apic_start) < TICK_COUNT);
result = (apic_start - apic) * 1000L / 5;
} else
#endif
{
rdtscl(tsc_start);

do {
apic = apic_read(APIC_TMCCT);
rdtscl(tsc);
} while ((tsc - tsc_start) < TICK_COUNT &&
(apic - apic_start) < TICK_COUNT);

result = (apic_start - apic) * 1000L * cpu_khz /
(tsc - tsc_start);
}
printk("result %d\n", result);

result = (apic_start - apic) * 1000L * cpu_khz / (tsc - tsc_start);

printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n",
result / 1000 / 1000, result / 1000 % 1000);
Expand Down Expand Up @@ -1115,6 +1129,13 @@ static __init int setup_noapicmaintimer(char *str)
}
__setup("noapicmaintimer", setup_noapicmaintimer);

static __init int setup_apicpmtimer(char *s)
{
apic_calibrate_pmtmr = 1;
return setup_apicmaintimer(NULL);
}
__setup("apicpmtimer", setup_apicpmtimer);

/* dummy parsing: see setup.c */

__setup("disableapic", setup_disableapic);
Expand Down
20 changes: 20 additions & 0 deletions trunk/arch/x86_64/kernel/pmtimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,26 @@ int pmtimer_mark_offset(void)
return lost - 1;
}

static unsigned pmtimer_wait_tick(void)
{
u32 a, b;
for (a = b = inl(pmtmr_ioport) & ACPI_PM_MASK;
a == b;
b = inl(pmtmr_ioport) & ACPI_PM_MASK)
;
return b;
}

/* note: wait time is rounded up to one tick */
void pmtimer_wait(unsigned us)
{
u32 a, b;
a = pmtimer_wait_tick();
do {
b = inl(pmtmr_ioport);
} while (cyc2us(b - a) < us);
}

void pmtimer_resume(void)
{
last_pmtmr_tick = inl(pmtmr_ioport);
Expand Down
1 change: 1 addition & 0 deletions trunk/include/asm-x86_64/proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ extern void iommu_hole_init(void);
extern void time_init_gtod(void);
extern int pmtimer_mark_offset(void);
extern void pmtimer_resume(void);
extern void pmtimer_wait(unsigned);
extern unsigned int do_gettimeoffset_pm(void);
#ifdef CONFIG_X86_PM_TIMER
extern u32 pmtmr_ioport;
Expand Down

0 comments on commit 0ee6baa

Please sign in to comment.