Obtain timer frequency from I-pipe
PATCH 2/5 Obtain timer frequency from I-pipe
This patch exploits the reworked ipipe_request_tickdev API that will be posted in a separate series. This way we can overcome the inaccuracy of Xenomai's current APIC timer frequency calibration. For !CONFIG_GENERIC_CLOCKEVENTS, the patch tries to obtain the frequency via the intermediate IPIPE_APIC_TIMER_FREQ API that will be provided on x86_64 only up to and including kernel 2.6.23 (later x86-kernels will be fully CLOCKEVENTS-based). We may also consider backporting that API to 2.6.20-i386.
Note that the user is still able to override the timer frequency via the related nucleus modules parameter.
Jan
--- include/asm-x86/hal.h | 30 ++++++++++++++++++++++++++++++ ksrc/arch/x86/hal-shared.c | 15 +++++++++++---- ksrc/arch/x86/hal_32.c | 22 +++++++++++----------- ksrc/arch/x86/hal_64.c | 3 --- 4 files changed, 52 insertions(+), 18 deletions(-)
include/asm-x86/hal.h +30 -0
@@ -1,6 +1,36 @@ +/** +* @ingroup hal +* @file +* +* Copyright (C) 2007 Philippe Gerum <[email protected]>. +* +* Xenomai is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Xenomai is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with Xenomai; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +* 02111-1307, USA. +*/ +#ifndef _XENO_ASM_X86_HAL_H#define _XENO_ASM_X86_HAL_H +#include <linux/ipipe.h> + +#ifndef IPIPE_APIC_TIMER_FREQ +# define RTHAL_COMPAT_TIMERFREQ (apic_read(APIC_TMICT) * HZ) +#else +# define RTHAL_COMPAT_TIMERFREQ IPIPE_APIC_TIMER_FREQ +#endif +enum rthal_ktimer_mode {/* <!> Must follow enum clock_event_mode */ KTIMER_MODE_UNUSED =0 , KTIMER_MODE_SHUTDOWN,
ksrc/arch/x86/hal-shared.c +11 -4
@@ -132,9 +132,11 @@ int rthal_timer_request(/* This code works both for UP+LAPIC and SMP configurations. */ #ifdef CONFIG_GENERIC_CLOCKEVENTS - err =ipipe_request_tickdev ("lapic" , mode_emul, tick_emul, cpu); +unsigned long tick_freq; +int res =ipipe_request_tickdev ("lapic" , mode_emul, tick_emul, cpu, + &tick_freq); -switch (err) { +switch (res) {case CLOCK_EVT_MODE_PERIODIC :/* oneshot tick emulation callback won't be used, ask * the caller to start an internal timer for emulating
@@ -156,10 +158,12 @@ int rthal_timer_request(return -ENODEV ;default : - return err; + return res; } + rthal_ktimer_saved_mode = res; - rthal_ktimer_saved_mode = err; +if (rthal_timerfreq_arg ==0 ) + rthal_tunables.timer_freq = tick_freq;#else /* !CONFIG_GENERIC_CLOCKEVENTS */ /* * When the local APIC is enabled for kernels lacking generic
@@ -170,6 +174,9 @@ int rthal_timer_request(*/ tickval =0 ; rthal_ktimer_saved_mode =KTIMER_MODE_PERIODIC ; + +if (rthal_timerfreq_arg ==0 ) + rthal_tunables.timer_freq =RTHAL_COMPAT_TIMERFREQ ;#endif /* !CONFIG_GENERIC_CLOCKEVENTS */ /*
ksrc/arch/x86/hal_32.c +11 -11
@@ -240,9 +240,11 @@ int rthal_timer_request(int tickval, err;#ifdef CONFIG_GENERIC_CLOCKEVENTS - err =ipipe_request_tickdev ("pit" , mode_emul, tick_emul, cpu); +unsigned long tick_freq; +int res =ipipe_request_tickdev ("pit" , mode_emul, tick_emul, cpu, + &tick_freq); -switch (err) { +switch (res) {case CLOCK_EVT_MODE_PERIODIC :/* oneshot tick emulation callback won't be used, ask * the caller to start an internal timer for emulating
@@ -264,10 +266,12 @@ int rthal_timer_request(return -ENOSYS ;default : - return err; + return res; } + rthal_ktimer_saved_mode = res; - rthal_ktimer_saved_mode = err; +if (rthal_timerfreq_arg ==0 ) + rthal_tunables.timer_freq = tick_freq;#else /* !CONFIG_GENERIC_CLOCKEVENTS */ /* * Out caller has to to emulate the periodic host tick by its
@@ -275,6 +279,9 @@ int rthal_timer_request(*/ tickval =1000000000UL /HZ ; rthal_ktimer_saved_mode =KTIMER_MODE_PERIODIC ; + +if (rthal_timerfreq_arg ==0 ) + rthal_tunables.timer_freq =CLOCK_TICK_RATE ;#endif /* !CONFIG_GENERIC_CLOCKEVENTS */ /*
@@ -394,13 +401,6 @@ int rthal_arch_init(void)rthal_setup_8254_tsc ();#endif /* CONFIG_X86_TSC */ - if (rthal_timerfreq_arg == 0) -#ifdef CONFIG_X86_LOCAL_APIC - rthal_timerfreq_arg =apic_read (APIC_TMICT ) *HZ ; -#else /* !CONFIG_X86_LOCAL_APIC */ - rthal_timerfreq_arg =CLOCK_TICK_RATE ; -#endif /* CONFIG_X86_LOCAL_APIC */ -return 0 ; }
ksrc/arch/x86/hal_64.c +0 -3
@@ -79,9 +79,6 @@ int rthal_arch_init(void)/* FIXME: 4Ghz barrier is close... */ rthal_cpufreq_arg =rthal_get_cpufreq (); -if (rthal_timerfreq_arg ==0 ) - rthal_timerfreq_arg =apic_read (APIC_TMICT ) *HZ ; -return 0 ; }