lkml.org 
[lkml]   [2011]   [Jun]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[22/85] time: Compensate for rounding on odd-frequency clocksources
    2.6.33-longterm review patch.  If anyone has any objections, please let us know.

    ------------------

    From: Kasper Pedersen <kkp2010@kasperkp.dk>

    commit a386b5af8edda1c742ce9f77891e112eefffc005 upstream.

    When the clocksource is not a multiple of HZ, the clock will be off. For
    acpi_pm, HZ=1000 the error is 127.111 ppm:

    The rounding of cycle_interval ends up generating a false error term in
    ntp_error accumulation since xtime_interval is not exactly 1/HZ. So, we
    subtract out the error caused by the rounding.

    This has been visible since 2.6.32-rc2
    commit a092ff0f90cae22b2ac8028ecd2c6f6c1a9e4601
    time: Implement logarithmic time accumulation
    That commit raised NTP_INTERVAL_FREQ and exposed the rounding error.

    testing tool: http://n1.taur.dk/permanent/testpmt.c
    Also tested with ntpd and a frequency counter.

    Signed-off-by: Kasper Pedersen <kkp2010@kasperkp.dk>
    Acked-by: john stultz <johnstul@us.ibm.com>
    Cc: John Kacur <jkacur@redhat.com>
    Cc: Clark Williams <williams@redhat.com>
    Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    kernel/time/timekeeping.c | 9 +++++++--
    1 file changed, 7 insertions(+), 2 deletions(-)

    --- a/kernel/time/timekeeping.c
    +++ b/kernel/time/timekeeping.c
    @@ -32,6 +32,8 @@ struct timekeeper {
    cycle_t cycle_interval;
    /* Number of clock shifted nano seconds in one NTP interval. */
    u64 xtime_interval;
    + /* shifted nano seconds left over when rounding cycle_interval */
    + s64 xtime_remainder;
    /* Raw nano seconds accumulated per NTP interval. */
    u32 raw_interval;

    @@ -62,7 +64,7 @@ struct timekeeper timekeeper;
    static void timekeeper_setup_internals(struct clocksource *clock)
    {
    cycle_t interval;
    - u64 tmp;
    + u64 tmp, ntpinterval;

    timekeeper.clock = clock;
    clock->cycle_last = clock->read(clock);
    @@ -70,6 +72,7 @@ static void timekeeper_setup_internals(s
    /* Do the ns -> cycle conversion first, using original mult */
    tmp = NTP_INTERVAL_LENGTH;
    tmp <<= clock->shift;
    + ntpinterval = tmp;
    tmp += clock->mult/2;
    do_div(tmp, clock->mult);
    if (tmp == 0)
    @@ -80,6 +83,7 @@ static void timekeeper_setup_internals(s

    /* Go back from cycles -> shifted ns */
    timekeeper.xtime_interval = (u64) interval * clock->mult;
    + timekeeper.xtime_remainder = ntpinterval - timekeeper.xtime_interval;
    timekeeper.raw_interval =
    ((u64) interval * clock->mult) >> clock->shift;

    @@ -771,7 +775,8 @@ static cycle_t logarithmic_accumulation(

    /* Accumulate error between NTP and clock interval */
    timekeeper.ntp_error += tick_length << shift;
    - timekeeper.ntp_error -= timekeeper.xtime_interval <<
    + timekeeper.ntp_error -=
    + (timekeeper.xtime_interval + timekeeper.xtime_remainder) <<
    (timekeeper.ntp_error_shift + shift);

    return offset;



    \
     
     \ /
      Last update: 2011-06-16 09:23    [W:0.025 / U:0.632 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site