On Tue, Apr 19, 2005 at 06:41:00PM -0700, john stultz wrote: > Andrew, All, > Currently the x86-64 HPET code assumes the entire HPET implementation > from the spec is present. This breaks on boxes that do not implement the > optional legacy timer replacement functionality portion of the spec. > > This patch fixes this issue, allowing x86-64 systems that cannot use the > HPET for the timer interrupt and RTC to still use the HPET as a time > source. I've tested this patch on a system systems without HPET, with > HPET but without legacy timer replacement, as well as HPET with legacy > timer replacement. > > I'm currently working on a similar patch for i386.
You should it get reviewed by Vojtech who wrote the original x86-64 HPET code. -Andi > > Please consider for your tree. > > thanks > -john > > Changelog: > A0: First sent to lkml > A1: Implemented suggestions from Venkatesh > A2: Whitespace cleanup. > > linux-2.6.12-rc2_hpet-nolegacy-fix_A2.patch > =========================================== > diff -Nru a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c > --- a/arch/x86_64/kernel/time.c 2005-04-19 18:28:49 -07:00 > +++ b/arch/x86_64/kernel/time.c 2005-04-19 18:28:49 -07:00 > @@ -60,6 +60,7 @@ > unsigned int cpu_khz; /* TSC clocks / > usec, not used here */ > static unsigned long hpet_period; /* fsecs / HPET clock */ > unsigned long hpet_tick; /* HPET clocks / > interrupt */ > +static int hpet_use_timer; > unsigned long vxtime_hz = PIT_TICK_RATE; > int report_lost_ticks; /* command line option > */ > unsigned long long monotonic_base; > @@ -297,7 +298,7 @@ > > last_offset = vxtime.last; > base = monotonic_base; > - this_offset = hpet_readl(HPET_T0_CMP) - hpet_tick; > + this_offset = hpet_readl(HPET_COUNTER); > > } while (read_seqretry(&xtime_lock, seq)); > offset = (this_offset - last_offset); > @@ -373,7 +374,14 @@ > > write_seqlock(&xtime_lock); > > - if (vxtime.hpet_address) { > + if (vxtime.hpet_address) > + offset = hpet_readl(HPET_COUNTER); > + > + if (hpet_use_timer) { > + /* if we're using the hpet timer functionality, > + * we can more accurately know the counter value > + * when the timer interrupt occured. > + */ > offset = hpet_readl(HPET_T0_CMP) - hpet_tick; > delay = hpet_readl(HPET_COUNTER) - offset; > } else { > @@ -794,17 +802,18 @@ > * Set up timer 0, as periodic with first interrupt to happen at hpet_tick, > * and period also hpet_tick. > */ > - > - hpet_writel(HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL | > + if (hpet_use_timer) { > + hpet_writel(HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL | > HPET_TN_32BIT, HPET_T0_CFG); > - hpet_writel(hpet_tick, HPET_T0_CMP); > - hpet_writel(hpet_tick, HPET_T0_CMP); /* AK: why twice? */ > - > + hpet_writel(hpet_tick, HPET_T0_CMP); > + hpet_writel(hpet_tick, HPET_T0_CMP); /* AK: why twice? */ > + cfg |= HPET_CFG_LEGACY; > + } > /* > * Go! > */ > > - cfg |= HPET_CFG_ENABLE | HPET_CFG_LEGACY; > + cfg |= HPET_CFG_ENABLE; > hpet_writel(cfg, HPET_CFG); > > return 0; > @@ -825,8 +834,7 @@ > > id = hpet_readl(HPET_ID); > > - if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER) || > - !(id & HPET_ID_LEGSUP)) > + if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER)) > return -1; > > hpet_period = hpet_readl(HPET_PERIOD); > @@ -836,6 +844,8 @@ > hpet_tick = (1000000000L * (USEC_PER_SEC / HZ) + hpet_period / 2) / > hpet_period; > > + hpet_use_timer = (id & HPET_ID_LEGSUP); > + > return hpet_timer_stop_set_go(hpet_tick); > } > > @@ -892,9 +902,11 @@ > set_normalized_timespec(&wall_to_monotonic, > -xtime.tv_sec, -xtime.tv_nsec); > > - if (!hpet_init()) { > + if (!hpet_init()) > vxtime_hz = (1000000000000000L + hpet_period / 2) / > hpet_period; > + > + if (hpet_use_timer) { > cpu_khz = hpet_calibrate_tsc(); > timename = "HPET"; > } else { > @@ -940,12 +952,12 @@ > if (oem_force_hpet_timer()) > notsc = 1; > if (vxtime.hpet_address && notsc) { > - timetype = "HPET"; > + timetype = hpet_use_timer ? "HPET" : "PIT/HPET"; > vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick; > vxtime.mode = VXTIME_HPET; > do_gettimeoffset = do_gettimeoffset_hpet; > } else { > - timetype = vxtime.hpet_address ? "HPET/TSC" : "PIT/TSC"; > + timetype = hpet_use_timer ? "HPET/TSC" : "PIT/TSC"; > vxtime.mode = VXTIME_TSC; > } > > > - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/