s390,time: revert direct ktime path for s390 clockevent device
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 22 Nov 2013 11:04:18 +0000 (12:04 +0100)
committerBen Hutchings <ben@decadent.org.uk>
Thu, 1 Jan 2015 01:27:51 +0000 (01:27 +0000)
commit 8adbf78ec4839c1dc4ff20c9a1f332a7bc99e6e6 upstream.

Git commit 4f37a68cdaf6dea833cfdded2a3e0c47c0f006da
"s390: Use direct ktime path for s390 clockevent device" makes use
of the CLOCK_EVT_FEAT_KTIME clockevent option to avoid the delta
calculation with ktime_get() in clockevents_program_event and the
get_tod_clock() in s390_next_event. This is based on the assumption
that the difference between the internal ktime and the hardware
clock is reflected in the wall_to_monotonic delta. But this is not
true, the ntp corrections are applied via changes to the tk->mult
multiplier and this is not reflected in wall_to_monotonic.

In theory this could be solved by using the raw monotonic clock
but it is simpler to switch back to the standard clock delta
calculation.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
[bwh: Backported to 3.2: s/get_tod_clock()/get_clock()/]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
arch/s390/kernel/time.c

index b2f44de..fd65e5e 100644 (file)
@@ -110,20 +110,10 @@ static void fixup_clock_comparator(unsigned long long delta)
        set_clock_comparator(S390_lowcore.clock_comparator);
 }
 
-static int s390_next_ktime(ktime_t expires,
+static int s390_next_event(unsigned long delta,
                           struct clock_event_device *evt)
 {
-       struct timespec ts;
-       u64 nsecs;
-
-       ts.tv_sec = ts.tv_nsec = 0;
-       monotonic_to_bootbased(&ts);
-       nsecs = ktime_to_ns(ktime_add(timespec_to_ktime(ts), expires));
-       do_div(nsecs, 125);
-       S390_lowcore.clock_comparator = sched_clock_base_cc + (nsecs << 9);
-       /* Program the maximum value if we have an overflow (== year 2042) */
-       if (unlikely(S390_lowcore.clock_comparator < sched_clock_base_cc))
-               S390_lowcore.clock_comparator = -1ULL;
+       S390_lowcore.clock_comparator = get_clock() + delta;
        set_clock_comparator(S390_lowcore.clock_comparator);
        return 0;
 }
@@ -148,15 +138,14 @@ void init_cpu_timer(void)
        cpu = smp_processor_id();
        cd = &per_cpu(comparators, cpu);
        cd->name                = "comparator";
-       cd->features            = CLOCK_EVT_FEAT_ONESHOT |
-                                 CLOCK_EVT_FEAT_KTIME;
+       cd->features            = CLOCK_EVT_FEAT_ONESHOT;
        cd->mult                = 16777;
        cd->shift               = 12;
        cd->min_delta_ns        = 1;
        cd->max_delta_ns        = LONG_MAX;
        cd->rating              = 400;
        cd->cpumask             = cpumask_of(cpu);
-       cd->set_next_ktime      = s390_next_ktime;
+       cd->set_next_event      = s390_next_event;
        cd->set_mode            = s390_set_mode;
 
        clockevents_register_device(cd);