mlx5: update timecounter at least twice per counter overflow
authorMiroslav Lichvar <mlichvar@redhat.com>
Mon, 3 Dec 2018 12:59:41 +0000 (13:59 +0100)
committerSaeed Mahameed <saeedm@mellanox.com>
Thu, 20 Dec 2018 13:06:00 +0000 (05:06 -0800)
The timecounter needs to be updated at least once in half of the
cyclecounter interval to prevent timecounter_cyc2time() interpreting a
new timestamp as an old value and causing a backward jump.

This would be an issue if the timecounter multiplier was so small that
the update interval would not be limited by the 64-bit overflow in
multiplication.

Shorten the calculated interval to make sure the timecounter is updated
in time even when the system clock is slowed down by up to 10%, the
multiplier is increased by up to 10%, and the scheduled overflow check
is late by 15%.

Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Ariel Levkovich <lariel@mellanox.com>
Cc: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c

index d27c239e7d6cc3402fca8f23757b55a0aaccdf4d..53f021df493475fd38fcd965a6cb04b1e1827699 100644 (file)
@@ -517,14 +517,14 @@ void mlx5_init_clock(struct mlx5_core_dev *mdev)
                         ktime_to_ns(ktime_get_real()));
 
        /* Calculate period in seconds to call the overflow watchdog - to make
-        * sure counter is checked at least once every wrap around.
+        * sure counter is checked at least twice every wrap around.
         * The period is calculated as the minimum between max HW cycles count
         * (The clock source mask) and max amount of cycles that can be
         * multiplied by clock multiplier where the result doesn't exceed
         * 64bits.
         */
        overflow_cycles = div64_u64(~0ULL >> 1, clock->cycles.mult);
-       overflow_cycles = min(overflow_cycles, clock->cycles.mask >> 1);
+       overflow_cycles = min(overflow_cycles, div_u64(clock->cycles.mask, 3));
 
        ns = cyclecounter_cyc2ns(&clock->cycles, overflow_cycles,
                                 frac, &frac);