diff options
-rw-r--r-- | arch/s390/Kconfig | 3 | ||||
-rw-r--r-- | arch/s390/defconfig | 1 | ||||
-rw-r--r-- | arch/s390/kernel/time.c | 88 |
3 files changed, 24 insertions, 68 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 51c2dfe89c62..608193cfe43f 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -30,6 +30,9 @@ config GENERIC_CALIBRATE_DELAY bool default y +config GENERIC_TIME + def_bool y + config GENERIC_BUST_SPINLOCK bool diff --git a/arch/s390/defconfig b/arch/s390/defconfig index b6cad75fd1f4..a3257398ea8d 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -9,6 +9,7 @@ CONFIG_STACKTRACE_SUPPORT=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_TIME=y CONFIG_S390=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 2c8c690688cb..6cceed4df73e 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -28,6 +28,7 @@ #include <linux/profile.h> #include <linux/timex.h> #include <linux/notifier.h> +#include <linux/clocksource.h> #include <asm/uaccess.h> #include <asm/delay.h> @@ -82,74 +83,6 @@ void tod_to_timeval(__u64 todval, struct timespec *xtime) xtime->tv_nsec = ((todval * 1000) >> 12); } -static inline unsigned long do_gettimeoffset(void) -{ - __u64 now; - - now = (get_clock() - jiffies_timer_cc) >> 12; - now -= (__u64) jiffies * USECS_PER_JIFFY; - return (unsigned long) now; -} - -/* - * This version of gettimeofday has microsecond resolution. - */ -void do_gettimeofday(struct timeval *tv) -{ - unsigned long flags; - unsigned long seq; - unsigned long usec, sec; - - do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - - sec = xtime.tv_sec; - usec = xtime.tv_nsec / 1000 + do_gettimeoffset(); - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - - while (usec >= 1000000) { - usec -= 1000000; - sec++; - } - - tv->tv_sec = sec; - tv->tv_usec = usec; -} - -EXPORT_SYMBOL(do_gettimeofday); - -int do_settimeofday(struct timespec *tv) -{ - time_t wtm_sec, sec = tv->tv_sec; - long wtm_nsec, nsec = tv->tv_nsec; - - if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) - return -EINVAL; - - write_seqlock_irq(&xtime_lock); - /* This is revolting. We need to set the xtime.tv_nsec - * correctly. However, the value in this location is - * is value at the last tick. - * Discover what correction gettimeofday - * would have done, and then undo it! - */ - nsec -= do_gettimeoffset() * 1000; - - wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); - wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); - - set_normalized_timespec(&xtime, sec, nsec); - set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); - - ntp_clear(); - write_sequnlock_irq(&xtime_lock); - clock_was_set(); - return 0; -} - -EXPORT_SYMBOL(do_settimeofday); - - #ifdef CONFIG_PROFILING #define s390_do_profile() profile_tick(CPU_PROFILING) #else @@ -340,6 +273,22 @@ void init_cpu_timer(void) extern void vtime_init(void); +static cycle_t read_tod_clock(void) +{ + return get_clock(); +} + +static struct clocksource clocksource_tod = { + .name = "tod", + .rating = 100, + .read = read_tod_clock, + .mask = -1ULL, + .mult = 1000, + .shift = 12, + .is_continuous = 1, +}; + + /* * Initialize the TOD clock and the CPU timer of * the boot cpu. @@ -384,6 +333,9 @@ void __init time_init(void) &ext_int_info_cc) != 0) panic("Couldn't request external interrupt 0x1004"); + if (clocksource_register(&clocksource_tod) != 0) + panic("Could not register TOD clock source"); + init_cpu_timer(); #ifdef CONFIG_NO_IDLE_HZ |