summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAriel Levkovich <lariel@mellanox.com>2018-06-25 19:12:02 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-07-28 07:49:11 +0200
commitadcecd4ab150f4e2dfdb2fcbf3f1394de6f9dd7a (patch)
tree013fda0475d84ffdbb9b487552b57aefe751e819
parente2ffdd646cf61ae1444d376d1ea1e756a495eff8 (diff)
net/mlx5: Adjust clock overflow work period
[ Upstream commit 33180bee86a8940a84950edca46315cd9dd6deb5 ] When driver converts HW timestamp to wall clock time it subtracts the last saved cycle counter from the HW timestamp and converts the difference to nanoseconds. The conversion is done by multiplying the cycles difference with the clock multiplier value as a first step and therefore the cycles difference should be small enough so that the multiplication product doesn't exceed 64bit. The overflow handling routine is in charge of updating the last saved cycle counter in driver and it is called periodically using kernel delayed workqueue. The delay period for this work is calculated using the max HW cycle counter value (a 41 bit mask) as a base which doesn't take the 64bit limit into account so the delay period may be incorrect and too long to prevent a large difference between the HW counter and the last saved counter in SW. This change adjusts the work period for the HW clock overflow work by taking the minimum between the previous value and the quotient of max u64 value and the clock multiplier value. Fixes: ef9814deafd0 ("net/mlx5e: Add HW timestamping (TS) support") Signed-off-by: Ariel Levkovich <lariel@mellanox.com> Reviewed-by: Eran Ben Elisha <eranbe@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_clock.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c b/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c
index 1612ec0d9103..f8b99d0b54d5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c
@@ -233,6 +233,7 @@ static void mlx5e_timestamp_init_config(struct mlx5e_tstamp *tstamp)
void mlx5e_timestamp_init(struct mlx5e_priv *priv)
{
struct mlx5e_tstamp *tstamp = &priv->tstamp;
+ u64 overflow_cycles;
u64 ns;
u64 frac = 0;
u32 dev_freq;
@@ -257,10 +258,17 @@ void mlx5e_timestamp_init(struct mlx5e_priv *priv)
/* Calculate period in seconds to call the overflow watchdog - to make
* sure counter is checked at least once 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.
*/
- ns = cyclecounter_cyc2ns(&tstamp->cycles, tstamp->cycles.mask,
+ overflow_cycles = div64_u64(~0ULL >> 1, tstamp->cycles.mult);
+ overflow_cycles = min(overflow_cycles, tstamp->cycles.mask >> 1);
+
+ ns = cyclecounter_cyc2ns(&tstamp->cycles, overflow_cycles,
frac, &frac);
- do_div(ns, NSEC_PER_SEC / 2 / HZ);
+ do_div(ns, NSEC_PER_SEC / HZ);
tstamp->overflow_period = ns;
INIT_DELAYED_WORK(&tstamp->overflow_work, mlx5e_timestamp_overflow);