Unify interface to persistent CMOS/RTC/whatever clock
RFC PATCH 1/1 Unify interface to persistent CMOS/RTC/whatever clock
All,
Almost every arch has some form of persistent clock (CMOS, RTC, etc)
which is normally used at boot time to initialize xtime and wall_to_monotonic. As part of the timekeeping consolidation, I propose the following generic interface to the arch specific persistent clock:
unsigned long read_persistent_clock(void);
Which returns seconds since the epoch.
Having this interface allows for the xtime/wall_to_monotonic initialization and management to be consolidated along with the rest of the timekeeping core. Additionally it provides a common interface to a low-res purely hardware driven clock, which is useful for watchdog functionality as seen in the hangcheck-timer module.
My first pass at this can be found below. There are a few arches (specifically: m32r, s390, sparc, sparc64) where I just didn't know what to do, or where I suspect I didn't get it right, so I've CC'ed those maintainers for suggestions.
I'll break this patch up before submitting it (using a generic weak function we can go arch-by-arch), but I wanted to get it out there to show I'm shooting for 100% coverage and see the initial reaction.
thanks
-john
arch/alpha/kernel/time.c | 77 +++++++++++++++++++++---------------------- arch/cris/kernel/crisksyms.c | 4 +- arch/cris/kernel/time.c | 4 +- arch/frv/kernel/time.c | 10 +++-- arch/h8300/kernel/time.c | 8 ++-- arch/i386/kernel/apm.c | 6 +-- arch/i386/kernel/time.c | 22 +++--------- arch/ia64/kernel/time.c | 14 +++---- arch/m32r/kernel/time.c | 6 +++ arch/m68k/kernel/time.c | 10 +++-- arch/m68knommu/kernel/time.c | 9 ++--- arch/mips/kernel/time.c | 11 ++---- arch/parisc/kernel/time.c | 19 +++------- arch/powerpc/kernel/time.c | 4 +- arch/ppc/kernel/time.c | 8 ++++ arch/s390/kernel/time.c | 6 +++ arch/sh/kernel/time.c | 20 +++++------ arch/sh64/kernel/time.c | 8 ++-- arch/sparc/kernel/time.c | 6 +++ arch/sparc64/kernel/time.c | 44 +++++++++++++----------- arch/um/kernel/time.c | 9 ++--- arch/v850/kernel/time.c | 8 +++- arch/x86_64/kernel/time.c | 12 +----- arch/xtensa/kernel/time.c | 24 ++++++------- kernel/timer.c | 8 +++- 25 files changed, 194 insertions(+), 163 deletions(-)
linux-2.6.18-rc4_timeofday-persistent-clock_C5.patch
============================================
arch/alpha/kernel/time.c +39 -38
@@ -349,44 +349,6 @@ time_init(void)bogomips yet, but this is close on a 500Mhz box. */ __delay (1000000 ); - sec =CMOS_READ (RTC_SECONDS ); - min =CMOS_READ (RTC_MINUTES ); - hour =CMOS_READ (RTC_HOURS ); - day =CMOS_READ (RTC_DAY_OF_MONTH ); - mon =CMOS_READ (RTC_MONTH ); - year =CMOS_READ (RTC_YEAR ); - -if (!(CMOS_READ (RTC_CONTROL ) &RTC_DM_BINARY ) ||RTC_ALWAYS_BCD ) { -BCD_TO_BIN (sec); -BCD_TO_BIN (min); -BCD_TO_BIN (hour); -BCD_TO_BIN (day); -BCD_TO_BIN (mon); -BCD_TO_BIN (year); - } - -/* PC-like is standard; used for year >= 70 */ - epoch =1900 ; -if (year <20 ) - epoch =2000 ; -else if (year >=20 && year <48 ) -/* NT epoch */ - epoch =1980 ; -else if (year >=48 && year <70 ) -/* Digital UNIX epoch */ - epoch =1952 ; - -printk (KERN_INFO "Using epoch = %d\n" , epoch); - -if ((year += epoch) <1970 ) - year +=100 ; - - xtime.tv_sec =mktime (year, mon, day, hour, min, sec); - xtime.tv_nsec =0 ; - - wall_to_monotonic.tv_sec -= xtime.tv_sec; - wall_to_monotonic.tv_nsec =0 ; -if (HZ > (1 <<16 )) {extern void __you_loose (void );__you_loose ();
@@ -507,6 +469,45 @@ do_settimeofday(struct timespec *tv)EXPORT_SYMBOL (do_settimeofday); +/* Read the CMOS clock and convert it to epoch based seconds */ +unsigned long read_persistent_clock (void ) +{ +unsigned int year, mon, day, hour, min, sec, epoch; + + sec =CMOS_READ (RTC_SECONDS ); + min =CMOS_READ (RTC_MINUTES ); + hour =CMOS_READ (RTC_HOURS ); + day =CMOS_READ (RTC_DAY_OF_MONTH ); + mon =CMOS_READ (RTC_MONTH ); + year =CMOS_READ (RTC_YEAR ); + +if (!(CMOS_READ (RTC_CONTROL ) &RTC_DM_BINARY ) ||RTC_ALWAYS_BCD ) { +BCD_TO_BIN (sec); +BCD_TO_BIN (min); +BCD_TO_BIN (hour); +BCD_TO_BIN (day); +BCD_TO_BIN (mon); +BCD_TO_BIN (year); + } + +/* PC-like is standard; used for year >= 70 */ + epoch =1900 ; +if (year <20 ) + epoch =2000 ; +else if (year >=20 && year <48 ) +/* NT epoch */ + epoch =1980 ; +else if (year >=48 && year <70 ) +/* Digital UNIX epoch */ + epoch =1952 ; + +printk (KERN_INFO "Using epoch = %d\n" , epoch); + +if ((year += epoch) <1970 ) + year +=100 ; + + return = mktime(year, mon, day, hour, min, sec); +}/* * In order to set the CMOS clock precisely, set_rtc_mmss has to be
arch/cris/kernel/crisksyms.c +2 -2
@@ -20,7 +20,7 @@#include <asm/pgtable.h> #include <asm/fasttimer.h> -extern unsigned long get_cmos_time (void ); +extern unsigned long read_persistent_clock (void );extern void __Udiv (void );extern void __Umod (void );extern void __Div (void );
@@ -32,7 +32,7 @@ extern void iounmap(volatile void * __io/* Platform dependent support */ EXPORT_SYMBOL (kernel_thread); -EXPORT_SYMBOL (get_cmos_time); +EXPORT_SYMBOL (read_persistent_clock);EXPORT_SYMBOL (loops_per_usec);/* String functions */
arch/cris/kernel/time.c +2 -2
@@ -168,7 +168,7 @@ int set_rtc_mmss(unsigned long nowtime)/* grab the time from the RTC chip */ unsigned long -get_cmos_time (void ) +read_persistent_clock (void ) {unsigned int year, mon, day, hour, min, sec;
@@ -204,7 +204,7 @@ voidupdate_xtime_from_cmos (void) {if (have_rtc) { - xtime.tv_sec =get_cmos_time (); + xtime.tv_sec =read_persistent_clock (); xtime.tv_nsec =0 ; } }
arch/frv/kernel/time.c +7 -3
@@ -119,7 +119,8 @@ void time_divisor_init(void)__set_TCSR_DATA (0 , base >>8 ); } -void time_init (void ) + +unsigned long read_persistent_clock (void ) {unsigned int year, mon, day, hour, min, sec;
@@ -135,9 +136,12 @@ void time_init(void)if ((year +=1900 ) <1970 ) year +=100 ; - xtime.tv_sec =mktime (year, mon, day, hour, min, sec); - xtime.tv_nsec =0 ; +return mktime (year, mon, day, hour, min, sec); + +} +void time_init (void ) +{/* install scheduling interrupt handler */ setup_irq (IRQ_CPU_TIMER0 , &timer_irq);
arch/h8300/kernel/time.c +5 -3
@@ -48,7 +48,7 @@ static void timer_interrupt(int irq, voiprofile_tick (CPU_PROFILING , regs); } -void time_init (void ) +unsigned long read_persistent_clock (void ) {unsigned int year, mon, day, hour, min, sec;
@@ -62,9 +62,11 @@ void time_init(void)if ((year +=1900 ) <1970 ) year +=100 ; - xtime.tv_sec =mktime (year, mon, day, hour, min, sec); - xtime.tv_nsec =0 ; +return mktime (year, mon, day, hour, min, sec); +} +void time_init (void ) +{platform_timer_setup (timer_interrupt); }
arch/i386/kernel/apm.c +3 -3
@@ -233,7 +233,7 @@#include "io_ports.h" -extern unsigned long get_cmos_time (void ); +extern unsigned long read_persistent_clock (void );extern void machine_real_restart (unsigned char *,int );#if defined(CONFIG_APM_DISPLAY_BLANK ) && defined(CONFIG_VT )
@@ -1155,7 +1155,7 @@ out:static void set_time (void ) {if (got_clock_diff) {/* Must know time zone in order to set clock */ - xtime.tv_sec =get_cmos_time () + clock_cmos_diff; + xtime.tv_sec =read_persistent_clock () + clock_cmos_diff; xtime.tv_nsec =0 ; } }
@@ -1166,7 +1166,7 @@ static void get_time_diff(void)/* * Estimate time zone so that set_time can update the clock */ - clock_cmos_diff = -get_cmos_time (); + clock_cmos_diff = -read_persistent_clock (); clock_cmos_diff +=get_seconds (); got_clock_diff =1 ;#endif
arch/i386/kernel/time.c +6 -16
@@ -203,7 +203,7 @@ irqreturn_t timer_interrupt(int irq, voi }/* not static: needed by APM */ -unsigned long get_cmos_time (void ) +unsigned long read_persistent_clock (void ) {unsigned long retval;unsigned long flags;
@@ -219,7 +219,7 @@ unsigned long get_cmos_time(void)return retval; } -EXPORT_SYMBOL (get_cmos_time); +EXPORT_SYMBOL (read_persistent_clock);static void sync_cmos_clock (unsigned long dummy);
@@ -277,9 +277,9 @@ static int timer_suspend(struct sys_devi/* * Estimate time zone so that set_time can update the clock */ - clock_cmos_diff = -get_cmos_time (); + clock_cmos_diff = -read_persistent_clock (); clock_cmos_diff +=get_seconds (); - sleep_start =get_cmos_time (); + sleep_start =read_persistent_clock ();return 0 ; }
@@ -294,8 +294,8 @@ static int timer_resume(struct sys_devichpet_reenable ();#endif setup_pit_timer (); - sec =get_cmos_time () + clock_cmos_diff; - sleep_length = (get_cmos_time () - sleep_start) *HZ ; + sec =read_persistent_clock () + clock_cmos_diff; + sleep_length = (read_persistent_clock () - sleep_start) *HZ ;write_seqlock_irqsave (&xtime_lock, flags); xtime.tv_sec = sec; xtime.tv_nsec =0 ;
@@ -334,11 +334,6 @@ extern void (*late_time_init)(void);/* Duplicate of time_init() below, with hpet_enable part added */ static void __init hpet_time_init (void ) { - xtime.tv_sec =get_cmos_time (); - xtime.tv_nsec = (INITIAL_JIFFIES %HZ ) * (NSEC_PER_SEC /HZ ); -set_normalized_timespec (&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); -if ((hpet_enable () >=0 ) && hpet_use_timer) {printk ("Using HPET for base-timer\n" ); }
@@ -359,10 +354,5 @@ void __init time_init(void) return; }#endif - xtime.tv_sec =get_cmos_time (); - xtime.tv_nsec = (INITIAL_JIFFIES %HZ ) * (NSEC_PER_SEC /HZ ); -set_normalized_timespec (&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); -time_init_hook (); }
arch/ia64/kernel/time.c +7 -7
@@ -240,18 +240,18 @@ void __devinit ia64_disable_timer(void)ia64_set_itv (1 <<16 ); } +unsigned long read_persistent_clock (void ) +{ +struct timespec ts; +efi_gettimeofday (&ts); +return ts.tv_sec; +} +void __init time_init (void ) {register_percpu_irq (IA64_TIMER_VECTOR , &timer_irqaction); -efi_gettimeofday (&xtime);ia64_init_itm (); - -/* -* Initialize wall_to_monotonic such that adding it to xtime will yield zero, the -* tv_nsec field must be normalized (i.e., 0 <= nsec < NSEC_PER_SEC). -*/ -set_normalized_timespec (&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); }/*
arch/m32r/kernel/time.c +6 -0
@@ -240,6 +240,12 @@ irqreturn_t timer_interrupt(int irq, voistruct irqaction irq0 = { timer_interrupt,IRQF_DISABLED ,CPU_MASK_NONE ,"MFT2" ,NULL ,NULL }; +/* XXX - Need some help here! */ +unsigned long read_persistent_clock (void ) +{ +return 0 ; +} +void __init time_init (void ) {unsigned int epoch, year, mon, day, hour, min, sec;
arch/m68k/kernel/time.c +6 -4
@@ -72,7 +72,7 @@ static irqreturn_t timer_interrupt(int ireturn IRQ_HANDLED ; } -void time_init (void ) +static unsigned long read_persistent_clock (void ) {struct rtc_time time;
@@ -81,12 +81,14 @@ void time_init(void)if ((time.tm_year +=1900 ) <1970 ) time.tm_year +=100 ; - xtime.tv_sec =mktime (time.tm_year, time.tm_mon, time.tm_mday, +return mktime (time.tm_year, time.tm_mon, time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec); - xtime.tv_nsec =0 ; } - wall_to_monotonic.tv_sec = -xtime.tv_sec; +return 0 ; +} +void time_init (void ) +{mach_sched_init (timer_interrupt); }
arch/m68knommu/kernel/time.c +5 -4
@@ -100,7 +100,7 @@ static irqreturn_t timer_interrupt(int ireturn (IRQ_HANDLED ); } -void time_init (void ) +static unsigned long read_persistent_clock (void ) {unsigned int year, mon, day, hour, min, sec;
@@ -111,10 +111,11 @@ void time_init(void)if ((year +=1900 ) <1970 ) year +=100 ; - xtime.tv_sec =mktime (year, mon, day, hour, min, sec); - xtime.tv_nsec =0 ; - wall_to_monotonic.tv_sec = -xtime.tv_sec; +return mktime (year, mon, day, hour, min, sec); +} +void time_init (void ) +{mach_sched_init (timer_interrupt); }
arch/mips/kernel/time.c +5 -6
@@ -625,6 +625,11 @@ static unsigned int __init calibrate_hptreturn frequency >> log_2_loops; } +unsigned long read_persistent_clock (void ) +{ +return rtc_mips_get_time (); +} +void __init time_init (void ) {if (board_time_init)
@@ -633,12 +638,6 @@ void __init time_init(void)if (!rtc_mips_set_mmss) rtc_mips_set_mmss = rtc_mips_set_time; - xtime.tv_sec =rtc_mips_get_time (); - xtime.tv_nsec =0 ; - -set_normalized_timespec (&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); -/* Choose appropriate high precision timer routines. */ if (!cpu_has_counter && !mips_hpt_read) {/* No high precision timer -- sorry. */
arch/parisc/kernel/time.c +7 -12
@@ -225,6 +225,13 @@ unsigned long long sched_clock(void)return (unsigned long long )jiffies * (1000000000 /HZ ); } +unsigned long read_persistent_clock (void ) +{ +struct tod_data ; +if (pdc_tod_read (&tod_data)) +return 0 ; +return tod.tod_sec; +}void __init time_init (void ) {
@@ -243,17 +250,5 @@ void __init time_init(void)/* kick off Itimer (CR16) */ mtctl (next_tick,16 ); -if (pdc_tod_read (&tod_data) ==0 ) { -write_seqlock_irq (&xtime_lock); - xtime.tv_sec = tod_data.tod_sec; - xtime.tv_nsec = tod_data.tod_usec *1000 ; -set_normalized_timespec (&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); -write_sequnlock_irq (&xtime_lock); - }else { -printk (KERN_ERR "Error reading tod clock\n" ); - xtime.tv_sec =0 ; - xtime.tv_nsec =0 ; - } }
arch/powerpc/kernel/time.c +2 -2
@@ -913,7 +913,7 @@ void __init generic_calibrate_decr(void)#endif } -unsigned long get_boot_time (void ) +unsigned long read_persistent_clock (void ) {struct rtc_time tm;
@@ -1011,7 +1011,7 @@ void __init time_init(void) tb_to_ns_scale = scale; tb_to_ns_shift = shift; - tm =get_boot_time (); + tm =read_persistent_clock ();write_seqlock_irqsave (&xtime_lock, flags);
arch/ppc/kernel/time.c +8 -0
@@ -281,6 +281,14 @@ int do_settimeofday(struct timespec *tv)EXPORT_SYMBOL (do_settimeofday); +unsigned long read_persistent_clock (void ) +{ +int sec =0 ; +if (ppc_md.get_rtc_time) + sec = ppc_md.get_rtc_time (); +return sec; +} +/* This function is only called on the boot processor */ void __init time_init (void ) {
arch/s390/kernel/time.c +6 -0
@@ -341,6 +341,12 @@ void init_cpu_timer(void)extern void vtime_init (void ); +unsigned long read_persistent_clock (void ) +{ +/* XXX I have no clue here. s390 folks, help! */ +return 0 ; +} +/* * Initialize the TOD clock and the CPU timer of * the boot cpu.
arch/sh/kernel/time.c +10 -10
@@ -161,6 +161,16 @@ device_initcall(timer_init_sysfs);void (*board_time_init)(void ); +unsigned long read_persistent_clock (void ) +{ +struct timespec ts; +if (rtc_get_time) { +rtc_get_time (&ts); +return ts.tv_sec; + } +return 0 ; +} +void __init time_init (void ) {if (board_time_init)
@@ -168,16 +178,6 @@ void __init time_init(void)clk_init (); -if (rtc_get_time) { -rtc_get_time (&xtime); - }else { - xtime.tv_sec =mktime (2000 ,1 ,1 ,0 ,0 ,0 ); - xtime.tv_nsec =0 ; - } - -set_normalized_timespec (&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); -/* * Find the timer to use as the system timer, it will be * initialized for us.
arch/sh64/kernel/time.c +5 -3
@@ -487,6 +487,11 @@ static irqreturn_t sh64_rtc_interrupt(instatic struct irqaction irq0 = { timer_interrupt,IRQF_DISABLED ,CPU_MASK_NONE ,"timer" ,NULL ,NULL };static struct irqaction irq1 = { sh64_rtc_interrupt,IRQF_DISABLED ,CPU_MASK_NONE ,"rtc" ,NULL ,NULL }; +unsigned long read_persistent_clock (void ) +{ +return get_rtc_time (); +} +void __init time_init (void ) {unsigned int cpu_clock, master_clock, bus_clock, module_clock;
@@ -511,9 +516,6 @@ void __init time_init(void)panic ("Unable to remap CPRC\n" ); } - xtime.tv_sec =get_rtc_time (); - xtime.tv_nsec =0 ; -setup_irq (TIMER_IRQ , &irq0);setup_irq (RTC_IRQ , &irq1);
arch/sparc/kernel/time.c +6 -0
@@ -366,6 +366,12 @@ static int __init clock_init(void)fs_initcall (clock_init);#endif /* !CONFIG_SUN4 */ +unsigned long read_persistent_clock (void ) +{ +/* XXX - help! not quite sure what to do here. */ +return 0 ; +} +void __init sbus_time_init (void ) {
arch/sparc64/kernel/time.c +24 -20
73 lines not on this page · raw message
arch/um/kernel/time.c +5 -4
@@ -123,13 +123,14 @@ static void register_timer(void)extern void (*late_time_init)(void ); +unsigned long read_persistent_clock (void ) +{ +return (long )os_nsecs ()/BILLION ; +} +void time_init (void ) {long long nsecs; - - nsecs =os_nsecs (); -set_normalized_timespec (&wall_to_monotonic, -nsecs /BILLION , - -nsecs %BILLION ); late_time_init = register_timer; }
arch/v850/kernel/time.c +7 -1
@@ -184,8 +184,14 @@ static struct irqaction timer_irqaction NULL }; +unsigned long read_persistent_clock (void ) +{ +struct timespec ts; +mach_gettimeofday (&ts); +return ts.tv_sec; +} +void time_init (void ) { -mach_gettimeofday (&xtime);mach_sched_init (&timer_irqaction); }
arch/x86_64/kernel/time.c +3 -9
@@ -511,7 +511,7 @@ unsigned long long sched_clock(void)return cycles_2_ns (a); } -static unsigned long get_cmos_time (void ) +static unsigned long read_persistent_clock (void ) {unsigned int year, mon, day, hour, min, sec;unsigned long flags;
@@ -901,12 +901,6 @@ void __init time_init(void)if (nohpet) vxtime.hpet_address =0 ; - xtime.tv_sec =get_cmos_time (); - xtime.tv_nsec =0 ; - -set_normalized_timespec (&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); -if (!hpet_init ()) vxtime_hz = (FSEC_PER_SEC + hpet_period /2 ) / hpet_period;else
@@ -1018,7 +1012,7 @@ static int timer_suspend(struct sys_devi/* * Estimate time zone so that set_time can update the clock */ -long cmos_time =get_cmos_time (); +long cmos_time =read_persistent_clock (); clock_cmos_diff = -cmos_time; clock_cmos_diff +=get_seconds ();
@@ -1030,7 +1024,7 @@ static int timer_resume(struct sys_devic {unsigned long flags;unsigned long sec; -unsigned long ctime =get_cmos_time (); +unsigned long ctime =read_persistent_clock ();unsigned long sleep_length = (ctime - sleep_start) *HZ ;if (vxtime.hpet_address)
arch/xtensa/kernel/time.c +11 -13
@@ -56,10 +56,19 @@ static struct irqaction timer_irqaction .name = "timer", }; -void __init time_init (void ) + +unsigned long read_persistent_clock (void ) {time_t sec_o, sec_n =0 ; +if (platform_get_rtc_time (&sec_o) ==0 ) +while (platform_get_rtc_time (&sec_n)) +if (sec_o != sec_n) +break ; +return sec_n; +} +void __init time_init (void ) +{/* The platform must provide a function to calibrate the processor * speed for the CALIBRATE. */
@@ -71,20 +80,9 @@ void __init time_init(void) (int)(ccount_per_jiffy/(10000/HZ))%100);#endif -/* Set time from RTC (if provided) */ - -if (platform_get_rtc_time (&sec_o) ==0 ) -while (platform_get_rtc_time (&sec_n)) -if (sec_o != sec_n) -break ; - - xtime.tv_nsec =0 ; - last_rtc_update = xtime.tv_sec = sec_n; + last_rtc_update = xtime.tv_sec; last_ccount_stamp =get_ccount (); -set_normalized_timespec (&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); -/* Initialize the linux timer interrupt. */ setup_irq (LINUX_TIMER_INT , &timer_irqaction);
kernel/timer.c +7 -1
@@ -961,10 +961,16 @@ void __init timekeeping_init(void)unsigned long flags;write_seqlock_irqsave (&xtime_lock, flags); +ntp_clear (); + clock =clocksource_get_next ();clocksource_calculate_interval (clock, tick_nsec); clock->cycle_last =clocksource_read (clock); -ntp_clear (); + + xtime.tv_sec =read_persistent_clock (); + xtime.tv_nsec = (INITIAL_JIFFIES %HZ ) * (NSEC_PER_SEC /HZ ); +set_normalized_timespec (&wall_to_monotonic, + -xtime.tv_sec, -xtime.tv_nsec);write_sequnlock_irqrestore (&xtime_lock, flags); }
Quoted 4 lines · john stultz
My first pass at this can be found below. There are a few arches (specifically: m32r, s390, sparc, sparc64) where I just didn't know what to do, or where I suspect I didn't get it right, so I've CC'ed those maintainers for suggestions.
Just realized I skipped the ARM arches. I'll get that fixed (or atleast make an attempt at it) before the next release.
thanks
-john
Quoted 5 lines · john stultz
My first pass at this can be found below. There are a few arches (specifically: m32r, s390, sparc, sparc64) where I just didn't know what
to do, or where I suspect I didn't get it right, so I've CC'ed those maintainers for suggestions.
But it is sooo easy ;-)
See patch below.
Signature · 57 lines
blue skies,
Martin.
Martin Schwidefsky
Linux for zSeries Development & Services
IBM Deutschland Entwicklung GmbH
"Reality continues to ruin my life." - Calvin.
---
arch/s390/kernel/time.c | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff -urpN linux-2.6/arch/s390/kernel/time.c linux-2.6-clock/arch/s390/kernel/time.c
--- linux-2.6/arch/s390/kernel/time.c 2006-08-17 10:34:58.000000000 +0200
+++ linux-2.6-clock/arch/s390/kernel/time.c 2006-08-17 11:05:28.000000000 +0200
@@ -40,6 +40,9 @@
#define USECS_PER_JIFFY ((unsigned long) 1000000/HZ)
#define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12)
+/* The value of the TOD clock for 1.1.1970. */
+#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
+
/*
* Create a small time difference between the timer interrupts
* on the different cpus to avoid lock contention.
@@ -343,8 +346,9 @@ extern void vtime_init(void);
unsigned long read_persistent_clock(void)
{
- /* XXX I have no clue here. s390 folks, help! */
- return 0;
+ __u64 tod = (get_clock() - TOD_UNIX_EPOCH) >> 12;
+ do_div(tod, 1000000);
+ return (unsigned long) tod;
}
/*
@@ -353,7 +357,6 @@ unsigned long read_persistent_clock(void
*/
void __init time_init(void)
{
- __u64 set_time_cc;
int cc;
/* kick the TOD clock */
@@ -378,9 +381,7 @@ void __init time_init(void)
/* set xtime */
xtime_cc = init_timer_cc + CLK_TICKS_PER_JIFFY;
- set_time_cc = init_timer_cc - 0x8126d60e46000000LL +
- (0x3c26700LL*1000000*4096);
- tod_to_timeval(set_time_cc, &xtime);
+ tod_to_timeval(init_timer_cc - TOD_UNIX_EPOCH, &xtime);
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);