diff mbox series

[net] net: dsa: sja1105: Ensure PTP time for rxtstamp reconstruction is not in the past

Message ID 20190928220817.24002-1-olteanv@gmail.com
State Accepted
Delegated to: David Miller
Headers show
Series [net] net: dsa: sja1105: Ensure PTP time for rxtstamp reconstruction is not in the past | expand

Commit Message

Vladimir Oltean Sept. 28, 2019, 10:08 p.m. UTC
Sometimes the PTP synchronization on the switch 'jumps':

  ptp4l[11241.155]: rms    8 max   16 freq -21732 +/-  11 delay   742 +/-   0
  ptp4l[11243.157]: rms    7 max   17 freq -21731 +/-  10 delay   744 +/-   0
  ptp4l[11245.160]: rms 33592410 max 134217731 freq +192422 +/- 8530253 delay   743 +/-   0
  ptp4l[11247.163]: rms 811631 max 964131 freq +10326 +/- 557785 delay   743 +/-   0
  ptp4l[11249.166]: rms 261936 max 533876 freq -304323 +/- 126371 delay   744 +/-   0
  ptp4l[11251.169]: rms 48700 max 57740 freq -20218 +/- 30532 delay   744 +/-   0
  ptp4l[11253.171]: rms 14570 max 30163 freq  -5568 +/- 7563 delay   742 +/-   0
  ptp4l[11255.174]: rms 2914 max 3440 freq -22001 +/- 1667 delay   744 +/-   1
  ptp4l[11257.177]: rms  811 max 1710 freq -22653 +/- 451 delay   744 +/-   1
  ptp4l[11259.180]: rms  177 max  218 freq -21695 +/-  89 delay   741 +/-   0
  ptp4l[11261.182]: rms   45 max   92 freq -21677 +/-  32 delay   742 +/-   0
  ptp4l[11263.186]: rms   14 max   32 freq -21733 +/-  11 delay   742 +/-   0
  ptp4l[11265.188]: rms    9 max   14 freq -21725 +/-  12 delay   742 +/-   0
  ptp4l[11267.191]: rms    9 max   16 freq -21727 +/-  13 delay   742 +/-   0
  ptp4l[11269.194]: rms    6 max   15 freq -21726 +/-   9 delay   743 +/-   0
  ptp4l[11271.197]: rms    8 max   15 freq -21728 +/-  11 delay   743 +/-   0
  ptp4l[11273.200]: rms    6 max   12 freq -21727 +/-   8 delay   743 +/-   0
  ptp4l[11275.202]: rms    9 max   17 freq -21720 +/-  11 delay   742 +/-   0
  ptp4l[11277.205]: rms    9 max   18 freq -21725 +/-  12 delay   742 +/-   0

Background: the switch only offers partial RX timestamps (24 bits) and
it is up to the driver to read the PTP clock to fill those timestamps up
to 64 bits. But the PTP clock readout needs to happen quickly enough (in
0.135 seconds, in fact), otherwise the PTP clock will wrap around 24
bits, condition which cannot be detected.

Looking at the 'max 134217731' value on output line 3, one can see that
in hex it is 0x8000003. Because the PTP clock resolution is 8 ns,
that means 0x1000000 in ticks, which is exactly 2^24. So indeed this is
a PTP clock wraparound, but the reason might be surprising.

What is going on is that sja1105_tstamp_reconstruct(priv, now, ts)
expects a "now" time that is later than the "ts" was snapshotted at.
This, of course, is obvious: we read the PTP time _after_ the partial RX
timestamp was received. However, the workqueue is processing frames from
a skb queue and reuses the same PTP time, read once at the beginning.
Normally the skb queue only contains one frame and all goes well. But
when the skb queue contains two frames, the second frame that gets
dequeued might have been partially timestamped by the RX MAC _after_ we
had read our PTP time initially.

The code was originally like that due to concerns that SPI access for
PTP time readout is a slow process, and we are time-constrained anyway
(aka: premature optimization). But some timing analysis reveals that the
time spent until the RX timestamp is completely reconstructed is 1 order
of magnitude lower than the 0.135 s deadline even under worst-case
conditions. So we can afford to read the PTP time for each frame in the
RX timestamping queue, which of course ensures that the full PTP time is
in the partial timestamp's future.

Fixes: f3097be21bf1 ("net: dsa: sja1105: Add a state machine for RX timestamping")
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
---
 drivers/net/dsa/sja1105/sja1105_main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Comments

David Miller Oct. 1, 2019, 12:22 a.m. UTC | #1
From: Vladimir Oltean <olteanv@gmail.com>
Date: Sun, 29 Sep 2019 01:08:17 +0300

> Sometimes the PTP synchronization on the switch 'jumps':
 ...
> Background: the switch only offers partial RX timestamps (24 bits) and
> it is up to the driver to read the PTP clock to fill those timestamps up
> to 64 bits. But the PTP clock readout needs to happen quickly enough (in
> 0.135 seconds, in fact), otherwise the PTP clock will wrap around 24
> bits, condition which cannot be detected.
> 
> Looking at the 'max 134217731' value on output line 3, one can see that
> in hex it is 0x8000003. Because the PTP clock resolution is 8 ns,
> that means 0x1000000 in ticks, which is exactly 2^24. So indeed this is
> a PTP clock wraparound, but the reason might be surprising.
> 
> What is going on is that sja1105_tstamp_reconstruct(priv, now, ts)
> expects a "now" time that is later than the "ts" was snapshotted at.
> This, of course, is obvious: we read the PTP time _after_ the partial RX
> timestamp was received. However, the workqueue is processing frames from
> a skb queue and reuses the same PTP time, read once at the beginning.
> Normally the skb queue only contains one frame and all goes well. But
> when the skb queue contains two frames, the second frame that gets
> dequeued might have been partially timestamped by the RX MAC _after_ we
> had read our PTP time initially.
> 
> The code was originally like that due to concerns that SPI access for
> PTP time readout is a slow process, and we are time-constrained anyway
> (aka: premature optimization). But some timing analysis reveals that the
> time spent until the RX timestamp is completely reconstructed is 1 order
> of magnitude lower than the 0.135 s deadline even under worst-case
> conditions. So we can afford to read the PTP time for each frame in the
> RX timestamping queue, which of course ensures that the full PTP time is
> in the partial timestamp's future.
> 
> Fixes: f3097be21bf1 ("net: dsa: sja1105: Add a state machine for RX timestamping")
> Signed-off-by: Vladimir Oltean <olteanv@gmail.com>

Applied and queued up for -stable, thanks.
diff mbox series

Patch

diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index b9def744bcb3..f3d38ff144c4 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -2005,12 +2005,12 @@  static void sja1105_rxtstamp_work(struct work_struct *work)
 
 	mutex_lock(&priv->ptp_lock);
 
-	now = priv->tstamp_cc.read(&priv->tstamp_cc);
-
 	while ((skb = skb_dequeue(&data->skb_rxtstamp_queue)) != NULL) {
 		struct skb_shared_hwtstamps *shwt = skb_hwtstamps(skb);
 		u64 ts;
 
+		now = priv->tstamp_cc.read(&priv->tstamp_cc);
+
 		*shwt = (struct skb_shared_hwtstamps) {0};
 
 		ts = SJA1105_SKB_CB(skb)->meta_tstamp;