Commit 3600be5f authored by Voon Weifeng's avatar Voon Weifeng Committed by David S. Miller

net: stmmac: add timestamp correction to rid CDC sync error

According to Synopsis DesignWare EQoS Databook, the Clock Domain Cross
synchronization error is introduced tue to the clock(GMII Tx/Rx clock)
being different at the capture as compared to the PTP
clock(clk_ptp_ref_i) that is used to generate the time.

The CDC synchronization error is almost equal to 2 times the clock
period of the PTP clock(clk_ptp_ref_i).

On a Intel Tigerlake platform (with Marvell 88E2110 external PHY):

Before applying this patch (with CDC synchronization error):
ptp4l[64.044]: rms    8 max   13 freq +30877 +/-  11 delay   216 +/-   0
ptp4l[65.047]: rms   13 max   20 freq +30869 +/-  17 delay   213 +/-   0
ptp4l[66.050]: rms   12 max   20 freq +30857 +/-  11 delay   213 +/-   0
ptp4l[67.052]: rms   11 max   22 freq +30849 +/-  10 delay   215 +/-   0
ptp4l[68.055]: rms   10 max   16 freq +30853 +/-  13 delay   215 +/-   0
ptp4l[69.057]: rms    7 max   13 freq +30848 +/-   9 delay   216 +/-   0
ptp4l[70.060]: rms    8 max   13 freq +30846 +/-  10 delay   216 +/-   0
ptp4l[71.063]: rms    9 max   15 freq +30836 +/-   8 delay   218 +/-   0

After applying this patch (CDC syncrhonization error is taken care of):
ptp4l[61.516]: rms  773 max  824 freq +31526 +/- 158 delay   200 +/-   0
ptp4l[62.519]: rms  427 max  596 freq +31668 +/-  39 delay   198 +/-   0
ptp4l[63.522]: rms  113 max  206 freq +31482 +/-  57 delay   198 +/-   0
ptp4l[64.525]: rms   40 max   56 freq +31316 +/-  29 delay   200 +/-   0
ptp4l[65.528]: rms   47 max   56 freq +31255 +/-  17 delay   200 +/-   0
ptp4l[66.531]: rms   26 max   36 freq +31246 +/-   9 delay   200 +/-   0
ptp4l[67.534]: rms   12 max   18 freq +31254 +/-  12 delay   202 +/-   0
ptp4l[68.537]: rms    7 max   12 freq +31263 +/-  10 delay   202 +/-   0
Signed-off-by: default avatarVoon Weifeng <weifeng.voon@intel.com>
Signed-off-by: default avatarWong Vee Khee <vee.khee.wong@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b7d5e297
...@@ -466,6 +466,7 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv, ...@@ -466,6 +466,7 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
{ {
struct skb_shared_hwtstamps shhwtstamp; struct skb_shared_hwtstamps shhwtstamp;
bool found = false; bool found = false;
s64 adjust = 0;
u64 ns = 0; u64 ns = 0;
if (!priv->hwts_tx_en) if (!priv->hwts_tx_en)
...@@ -484,6 +485,13 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv, ...@@ -484,6 +485,13 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
} }
if (found) { if (found) {
/* Correct the clk domain crossing(CDC) error */
if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate) {
adjust += -(2 * (NSEC_PER_SEC /
priv->plat->clk_ptp_rate));
ns += adjust;
}
memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
shhwtstamp.hwtstamp = ns_to_ktime(ns); shhwtstamp.hwtstamp = ns_to_ktime(ns);
...@@ -507,6 +515,7 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p, ...@@ -507,6 +515,7 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,
{ {
struct skb_shared_hwtstamps *shhwtstamp = NULL; struct skb_shared_hwtstamps *shhwtstamp = NULL;
struct dma_desc *desc = p; struct dma_desc *desc = p;
u64 adjust = 0;
u64 ns = 0; u64 ns = 0;
if (!priv->hwts_rx_en) if (!priv->hwts_rx_en)
...@@ -518,6 +527,13 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p, ...@@ -518,6 +527,13 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,
/* Check if timestamp is available */ /* Check if timestamp is available */
if (stmmac_get_rx_timestamp_status(priv, p, np, priv->adv_ts)) { if (stmmac_get_rx_timestamp_status(priv, p, np, priv->adv_ts)) {
stmmac_get_timestamp(priv, desc, priv->adv_ts, &ns); stmmac_get_timestamp(priv, desc, priv->adv_ts, &ns);
/* Correct the clk domain crossing(CDC) error */
if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate) {
adjust += 2 * (NSEC_PER_SEC / priv->plat->clk_ptp_rate);
ns -= adjust;
}
netdev_dbg(priv->dev, "get valid RX hw timestamp %llu\n", ns); netdev_dbg(priv->dev, "get valid RX hw timestamp %llu\n", ns);
shhwtstamp = skb_hwtstamps(skb); shhwtstamp = skb_hwtstamps(skb);
memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment