Page MenuHomeFreeBSD

D61430.1794597964.diff
No OneTemporary

Authored By
Unknown
Size
4 KB
Referenced Files
None
Subscribers
None

D61430.1794597964.diff

diff --git a/sys/dev/mlx5/mlx5_en/en.h b/sys/dev/mlx5/mlx5_en/en.h
--- a/sys/dev/mlx5/mlx5_en/en.h
+++ b/sys/dev/mlx5/mlx5_en/en.h
@@ -1055,6 +1055,7 @@
#include <dev/mlx5/mlx5_en/en_hw_tls_rx.h>
#define MLX5E_TSTMP_PREC 10
+#define MLX5E_TSTMP_SPLIT 20
struct mlx5e_clbr_point {
uint64_t base_curr;
@@ -1142,7 +1143,6 @@
int clbr_curr;
struct mlx5e_clbr_point clbr_points[2];
u_int clbr_gen;
- uint64_t cclk;
struct mlx5e_dcbx dcbx;
bool sw_is_port_buf_owner;
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
--- a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
+++ b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
@@ -5089,8 +5089,6 @@
&priv->clbr_done, 0,
"RX timestamps calibration state");
callout_init(&priv->tstmp_clbr, 1);
- /* Pull out the frequency of the clock in hz */
- priv->cclk = (uint64_t)MLX5_CAP_GEN(mdev, device_frequency_khz) * 1000ULL;
mlx5e_reset_calibration_callout(priv);
pa.pa_version = PFIL_VERSION;
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c b/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c
--- a/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c
+++ b/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c
@@ -261,9 +261,8 @@
mlx5e_mbuf_tstmp(struct mlx5e_priv *priv, uint64_t hw_tstmp)
{
struct mlx5e_clbr_point *cp, dcp;
- uint64_t tstmp_sec, tstmp_nsec;
uint64_t hw_clocks;
- uint64_t rt_cur_to_prev, res_s, res_n, res_s_modulo, res;
+ uint64_t rt_cur_to_prev, res_ivl, res_hi, res_lo, res_hi_modulo, res;
uint64_t hw_clk_div;
u_int gen;
@@ -285,37 +284,46 @@
* With the constraints that we cannot use float and we
* don't want to overflow the uint64_t numbers we are using.
*
- * The plan is to take the clocking value of the hw timestamps
- * and split them into seconds and nanosecond equivalent portions.
- * Then we operate on the two portions seperately making sure to
- * bring back the carry over from the seconds when we divide.
+ * The plan is to first take out of the hw timestamp delta the
+ * whole calibration intervals it contains. Each of them
+ * converts to exactly (cur_time - prev_time), and what is left
+ * is shorter than one calibration interval, so the rest of the
+ * computation does not depend on how far the timestamp is from
+ * the calibration point.
*
- * First up lets get the two divided into separate entities
- * i.e. the seconds. We use the clock frequency for this.
- * Note that priv->cclk was setup with the clock frequency
- * in hz so we are all set to go.
+ * Then we split what is left into high and low parts at
+ * 2^MLX5E_TSTMP_SPLIT clocks, and operate on the two parts
+ * seperately, making sure to bring back the carry over from the
+ * high part when we divide. The low part is less than
+ * 2^MLX5E_TSTMP_SPLIT and is multiplied by the calibration
+ * interval in nanoseconds. The carry over is less than the
+ * calibration interval in clocks and is multiplied by
+ * 2^MLX5E_TSTMP_SPLIT. The split must be small enough to keep
+ * both products within uint64_t for fast clocks and long
+ * calibration intervals.
+ *
+ * hw_clk_div cannot be zero, mlx5e_calibration_callout() does
+ * not publish a calibration point unless the hw clock advanced.
*/
- hw_clocks = hw_tstmp - dcp.clbr_hw_prev;
- tstmp_sec = hw_clocks / priv->cclk;
- tstmp_nsec = hw_clocks % priv->cclk;
- /* Now work with them separately */
- rt_cur_to_prev = (dcp.base_curr - dcp.base_prev);
- res_s = tstmp_sec * rt_cur_to_prev;
- res_n = tstmp_nsec * rt_cur_to_prev;
- /* Now lets get our divider */
+ rt_cur_to_prev = dcp.base_curr - dcp.base_prev;
hw_clk_div = dcp.clbr_hw_curr - dcp.clbr_hw_prev;
- /* Make sure to save the remainder from the seconds divide */
- res_s_modulo = res_s % hw_clk_div;
- res_s /= hw_clk_div;
- /* scale the remainder to where it should be */
- res_s_modulo *= priv->cclk;
- /* Now add in the remainder */
- res_n += res_s_modulo;
+ hw_clocks = hw_tstmp - dcp.clbr_hw_prev;
+ /* Take out the whole calibration intervals */
+ res_ivl = (hw_clocks / hw_clk_div) * rt_cur_to_prev;
+ hw_clocks %= hw_clk_div;
+ /* Now split the rest and work with the parts separately */
+ res_hi = (hw_clocks >> MLX5E_TSTMP_SPLIT) * rt_cur_to_prev;
+ res_lo = (hw_clocks & ((1ULL << MLX5E_TSTMP_SPLIT) - 1)) *
+ rt_cur_to_prev;
+ /* Make sure to save the remainder from the high part divide */
+ res_hi_modulo = res_hi % hw_clk_div;
+ res_hi /= hw_clk_div;
+ /* Scale the remainder to where it should be and add it in */
+ res_lo += res_hi_modulo << MLX5E_TSTMP_SPLIT;
/* Now do the divide */
- res_n /= hw_clk_div;
- res_s *= priv->cclk;
- /* Recombine the two */
- res = res_s + res_n;
+ res_lo /= hw_clk_div;
+ /* Recombine the three */
+ res = res_ivl + (res_hi << MLX5E_TSTMP_SPLIT) + res_lo;
/* And now add in the base time to get to the real timestamp */
res += dcp.base_prev;
return (res);

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 13, 7:26 PM (8 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41707405
Default Alt Text
D61430.1794597964.diff (4 KB)

Event Timeline