diff options
Diffstat (limited to 'arch/s390/kernel/time.c')
-rw-r--r-- | arch/s390/kernel/time.c | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 369ff02c4ab2..6ded50dfa75a 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
@@ -253,32 +253,52 @@ void update_vsyscall_tz(void) | |||
253 | */ | 253 | */ |
254 | void __init time_init(void) | 254 | void __init time_init(void) |
255 | { | 255 | { |
256 | struct timespec ts; | ||
257 | unsigned long flags; | ||
258 | cycle_t now; | ||
259 | |||
256 | /* Reset time synchronization interfaces. */ | 260 | /* Reset time synchronization interfaces. */ |
257 | etr_reset(); | 261 | etr_reset(); |
258 | stp_reset(); | 262 | stp_reset(); |
259 | 263 | ||
260 | /* set xtime */ | ||
261 | tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, &xtime); | ||
262 | set_normalized_timespec(&wall_to_monotonic, | ||
263 | -xtime.tv_sec, -xtime.tv_nsec); | ||
264 | |||
265 | /* request the clock comparator external interrupt */ | 264 | /* request the clock comparator external interrupt */ |
266 | if (register_early_external_interrupt(0x1004, | 265 | if (register_early_external_interrupt(0x1004, |
267 | clock_comparator_interrupt, | 266 | clock_comparator_interrupt, |
268 | &ext_int_info_cc) != 0) | 267 | &ext_int_info_cc) != 0) |
269 | panic("Couldn't request external interrupt 0x1004"); | 268 | panic("Couldn't request external interrupt 0x1004"); |
270 | 269 | ||
271 | if (clocksource_register(&clocksource_tod) != 0) | ||
272 | panic("Could not register TOD clock source"); | ||
273 | |||
274 | /* request the timing alert external interrupt */ | 270 | /* request the timing alert external interrupt */ |
275 | if (register_early_external_interrupt(0x1406, | 271 | if (register_early_external_interrupt(0x1406, |
276 | timing_alert_interrupt, | 272 | timing_alert_interrupt, |
277 | &ext_int_etr_cc) != 0) | 273 | &ext_int_etr_cc) != 0) |
278 | panic("Couldn't request external interrupt 0x1406"); | 274 | panic("Couldn't request external interrupt 0x1406"); |
279 | 275 | ||
276 | if (clocksource_register(&clocksource_tod) != 0) | ||
277 | panic("Could not register TOD clock source"); | ||
278 | |||
279 | /* | ||
280 | * The TOD clock is an accurate clock. The xtime should be | ||
281 | * initialized in a way that the difference between TOD and | ||
282 | * xtime is reasonably small. Too bad that timekeeping_init | ||
283 | * sets xtime.tv_nsec to zero. In addition the clock source | ||
284 | * change from the jiffies clock source to the TOD clock | ||
285 | * source add another error of up to 1/HZ second. The same | ||
286 | * function sets wall_to_monotonic to a value that is too | ||
287 | * small for /proc/uptime to be accurate. | ||
288 | * Reset xtime and wall_to_monotonic to sane values. | ||
289 | */ | ||
290 | write_seqlock_irqsave(&xtime_lock, flags); | ||
291 | now = get_clock(); | ||
292 | tod_to_timeval(now - TOD_UNIX_EPOCH, &xtime); | ||
293 | clocksource_tod.cycle_last = now; | ||
294 | clocksource_tod.raw_time = xtime; | ||
295 | tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, &ts); | ||
296 | set_normalized_timespec(&wall_to_monotonic, -ts.tv_sec, -ts.tv_nsec); | ||
297 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
298 | |||
280 | /* Enable TOD clock interrupts on the boot cpu. */ | 299 | /* Enable TOD clock interrupts on the boot cpu. */ |
281 | init_cpu_timer(); | 300 | init_cpu_timer(); |
301 | |||
282 | /* Enable cpu timer interrupts on the boot cpu. */ | 302 | /* Enable cpu timer interrupts on the boot cpu. */ |
283 | vtime_init(); | 303 | vtime_init(); |
284 | } | 304 | } |