Re: [PATCH] X86_64: fix hpet for systems that don't support legacy replacement (v. A2)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux