Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: dsa: sja1105: implement TX timestamping for SJA1110

The TX timestamping procedure for SJA1105 is a bit unconventional
because the transmit procedure itself is unconventional.

Control packets (and therefore PTP as well) are transmitted to a
specific port in SJA1105 using "management routes" which must be written
over SPI to the switch. These are one-shot rules that match by
destination MAC address on traffic coming from the CPU port, and select
the precise destination port for that packet. So to transmit a packet
from NET_TX softirq context, we actually need to defer to a process
context so that we can perform that SPI write before we send the packet.
The DSA master dev_queue_xmit() runs in process context, and we poll
until the switch confirms it took the TX timestamp, then we annotate the
skb clone with that TX timestamp. This is why the sja1105 driver does
not need an skb queue for TX timestamping.

But the SJA1110 is a bit (not much!) more conventional, and you can
request 2-step TX timestamping through the DSA header, as well as give
the switch a cookie (timestamp ID) which it will give back to you when
it has the timestamp. So now we do need a queue for keeping the skb
clones until their TX timestamps become available.

The interesting part is that the metadata frames from SJA1105 haven't
disappeared completely. On SJA1105 they were used as follow-ups which
contained RX timestamps, but on SJA1110 they are actually TX completion
packets, which contain a variable (up to 32) array of timestamps.
Why an array? Because:
- not only is the TX timestamp on the egress port being communicated,
but also the RX timestamp on the CPU port. Nice, but we don't care
about that, so we ignore it.
- because a packet could be multicast to multiple egress ports, each
port takes its own timestamp, and the TX completion packet contains
the individual timestamps on each port.

This is unconventional because switches typically have a timestamping
FIFO and raise an interrupt, but this one doesn't. So the tagger needs
to detect and parse meta frames, and call into the main switch driver,
which pairs the timestamps with the skbs in the TX timestamping queue
which are waiting for one.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Vladimir Oltean and committed by
David S. Miller
566b18c8 30b73242

+156
+1
drivers/net/dsa/sja1105/sja1105.h
··· 131 131 void (*ptp_cmd_packing)(u8 *buf, struct sja1105_ptp_cmd *cmd, 132 132 enum packing_op op); 133 133 bool (*rxtstamp)(struct dsa_switch *ds, int port, struct sk_buff *skb); 134 + void (*txtstamp)(struct dsa_switch *ds, int port, struct sk_buff *skb); 134 135 int (*clocking_setup)(struct sja1105_private *priv); 135 136 const char *name; 136 137 bool supports_mii[SJA1105_MAX_NUM_PORTS];
+69
drivers/net/dsa/sja1105/sja1105_ptp.c
··· 79 79 priv->tagger_data.stampable_skb = NULL; 80 80 } 81 81 ptp_cancel_worker_sync(ptp_data->clock); 82 + skb_queue_purge(&ptp_data->skb_txtstamp_queue); 82 83 skb_queue_purge(&ptp_data->skb_rxtstamp_queue); 83 84 84 85 return sja1105_static_config_reload(priv, SJA1105_RX_HWTSTAMPING); ··· 452 451 return priv->info->rxtstamp(ds, port, skb); 453 452 } 454 453 454 + void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, u8 ts_id, 455 + enum sja1110_meta_tstamp dir, u64 tstamp) 456 + { 457 + struct sja1105_private *priv = ds->priv; 458 + struct sja1105_ptp_data *ptp_data = &priv->ptp_data; 459 + struct sk_buff *skb, *skb_tmp, *skb_match = NULL; 460 + struct skb_shared_hwtstamps shwt = {0}; 461 + 462 + /* We don't care about RX timestamps on the CPU port */ 463 + if (dir == SJA1110_META_TSTAMP_RX) 464 + return; 465 + 466 + spin_lock(&ptp_data->skb_txtstamp_queue.lock); 467 + 468 + skb_queue_walk_safe(&ptp_data->skb_txtstamp_queue, skb, skb_tmp) { 469 + if (SJA1105_SKB_CB(skb)->ts_id != ts_id) 470 + continue; 471 + 472 + __skb_unlink(skb, &ptp_data->skb_txtstamp_queue); 473 + skb_match = skb; 474 + 475 + break; 476 + } 477 + 478 + spin_unlock(&ptp_data->skb_txtstamp_queue.lock); 479 + 480 + if (WARN_ON(!skb_match)) 481 + return; 482 + 483 + shwt.hwtstamp = ns_to_ktime(sja1105_ticks_to_ns(tstamp)); 484 + skb_complete_tx_timestamp(skb_match, &shwt); 485 + } 486 + EXPORT_SYMBOL_GPL(sja1110_process_meta_tstamp); 487 + 488 + /* In addition to cloning the skb which is done by the common 489 + * sja1105_port_txtstamp, we need to generate a timestamp ID and save the 490 + * packet to the TX timestamping queue. 491 + */ 492 + void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb) 493 + { 494 + struct sk_buff *clone = SJA1105_SKB_CB(skb)->clone; 495 + struct sja1105_private *priv = ds->priv; 496 + struct sja1105_ptp_data *ptp_data = &priv->ptp_data; 497 + struct sja1105_port *sp = &priv->ports[port]; 498 + u8 ts_id; 499 + 500 + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 501 + 502 + spin_lock(&sp->data->meta_lock); 503 + 504 + ts_id = sp->data->ts_id; 505 + /* Deal automatically with 8-bit wraparound */ 506 + sp->data->ts_id++; 507 + 508 + SJA1105_SKB_CB(clone)->ts_id = ts_id; 509 + 510 + spin_unlock(&sp->data->meta_lock); 511 + 512 + skb_queue_tail(&ptp_data->skb_txtstamp_queue, clone); 513 + } 514 + 455 515 /* Called from dsa_skb_tx_timestamp. This callback is just to clone 456 516 * the skb and have it available in SJA1105_SKB_CB in the .port_deferred_xmit 457 517 * callback, where we will timestamp it synchronously. ··· 531 469 return; 532 470 533 471 SJA1105_SKB_CB(skb)->clone = clone; 472 + 473 + if (priv->info->txtstamp) 474 + priv->info->txtstamp(ds, port, skb); 534 475 } 535 476 536 477 static int sja1105_ptp_reset(struct dsa_switch *ds) ··· 950 885 .n_per_out = 1, 951 886 }; 952 887 888 + /* Only used on SJA1105 */ 953 889 skb_queue_head_init(&ptp_data->skb_rxtstamp_queue); 890 + /* Only used on SJA1110 */ 891 + skb_queue_head_init(&ptp_data->skb_txtstamp_queue); 954 892 spin_lock_init(&tagger_data->meta_lock); 955 893 956 894 ptp_data->clock = ptp_clock_register(&ptp_data->caps, ds->dev); ··· 978 910 979 911 del_timer_sync(&ptp_data->extts_timer); 980 912 ptp_cancel_worker_sync(ptp_data->clock); 913 + skb_queue_purge(&ptp_data->skb_txtstamp_queue); 981 914 skb_queue_purge(&ptp_data->skb_rxtstamp_queue); 982 915 ptp_clock_unregister(ptp_data->clock); 983 916 ptp_data->clock = NULL;
+7
drivers/net/dsa/sja1105/sja1105_ptp.h
··· 75 75 76 76 struct sja1105_ptp_data { 77 77 struct timer_list extts_timer; 78 + /* Used only on SJA1105 to reconstruct partial timestamps */ 78 79 struct sk_buff_head skb_rxtstamp_queue; 80 + /* Used on SJA1110 where meta frames are generated only for 81 + * 2-step TX timestamps 82 + */ 83 + struct sk_buff_head skb_txtstamp_queue; 79 84 struct ptp_clock_info caps; 80 85 struct ptp_clock *clock; 81 86 struct sja1105_ptp_cmd cmd; ··· 129 124 130 125 bool sja1105_rxtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb); 131 126 bool sja1110_rxtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb); 127 + void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb); 132 128 133 129 #else 134 130 ··· 195 189 196 190 #define sja1105_rxtstamp NULL 197 191 #define sja1110_rxtstamp NULL 192 + #define sja1110_txtstamp NULL 198 193 199 194 #endif /* IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP) */ 200 195
+4
drivers/net/dsa/sja1105/sja1105_spi.c
··· 788 788 .fdb_del_cmd = sja1105pqrs_fdb_del, 789 789 .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, 790 790 .rxtstamp = sja1110_rxtstamp, 791 + .txtstamp = sja1110_txtstamp, 791 792 .clocking_setup = sja1110_clocking_setup, 792 793 .port_speed = { 793 794 [SJA1105_SPEED_AUTO] = 0, ··· 837 836 .fdb_del_cmd = sja1105pqrs_fdb_del, 838 837 .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, 839 838 .rxtstamp = sja1110_rxtstamp, 839 + .txtstamp = sja1110_txtstamp, 840 840 .clocking_setup = sja1110_clocking_setup, 841 841 .port_speed = { 842 842 [SJA1105_SPEED_AUTO] = 0, ··· 886 884 .fdb_del_cmd = sja1105pqrs_fdb_del, 887 885 .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, 888 886 .rxtstamp = sja1110_rxtstamp, 887 + .txtstamp = sja1110_txtstamp, 889 888 .clocking_setup = sja1110_clocking_setup, 890 889 .port_speed = { 891 890 [SJA1105_SPEED_AUTO] = 0, ··· 935 932 .fdb_del_cmd = sja1105pqrs_fdb_del, 936 933 .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, 937 934 .rxtstamp = sja1110_rxtstamp, 935 + .txtstamp = sja1110_txtstamp, 938 936 .clocking_setup = sja1110_clocking_setup, 939 937 .port_speed = { 940 938 [SJA1105_SPEED_AUTO] = 0,
+23
include/linux/dsa/sja1105.h
··· 45 45 */ 46 46 spinlock_t meta_lock; 47 47 unsigned long state; 48 + u8 ts_id; 48 49 }; 49 50 50 51 struct sja1105_skb_cb { 51 52 struct sk_buff *clone; 52 53 u64 tstamp; 54 + /* Only valid for packets cloned for 2-step TX timestamping */ 55 + u8 ts_id; 53 56 }; 54 57 55 58 #define SJA1105_SKB_CB(skb) \ ··· 68 65 bool hwts_tx_en; 69 66 u16 xmit_tpid; 70 67 }; 68 + 69 + enum sja1110_meta_tstamp { 70 + SJA1110_META_TSTAMP_TX = 0, 71 + SJA1110_META_TSTAMP_RX = 1, 72 + }; 73 + 74 + #if IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP) 75 + 76 + void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, u8 ts_id, 77 + enum sja1110_meta_tstamp dir, u64 tstamp); 78 + 79 + #else 80 + 81 + static inline void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, 82 + u8 ts_id, enum sja1110_meta_tstamp dir, 83 + u64 tstamp) 84 + { 85 + } 86 + 87 + #endif /* IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP) */ 71 88 72 89 #endif /* _NET_DSA_SJA1105_H */
+52
net/dsa/tag_sja1105.c
··· 25 25 #define SJA1110_RX_TRAILER_SWITCH_ID(x) (((x) & GENMASK(7, 4)) >> 4) 26 26 #define SJA1110_RX_TRAILER_SRC_PORT(x) ((x) & GENMASK(3, 0)) 27 27 28 + /* Meta frame format (for 2-step TX timestamps) */ 29 + #define SJA1110_RX_HEADER_N_TS(x) (((x) & GENMASK(8, 4)) >> 4) 30 + 28 31 /* TX header */ 29 32 #define SJA1110_TX_HEADER_UPDATE_TC BIT(14) 30 33 #define SJA1110_TX_HEADER_TAKE_TS BIT(13) ··· 45 42 #define SJA1110_TX_TRAILER_PRIO(x) (((x) << 21) & GENMASK(23, 21)) 46 43 #define SJA1110_TX_TRAILER_SWITCHID(x) (((x) << 12) & GENMASK(15, 12)) 47 44 #define SJA1110_TX_TRAILER_DESTPORTS(x) (((x) << 1) & GENMASK(11, 1)) 45 + 46 + #define SJA1110_META_TSTAMP_SIZE 10 48 47 49 48 #define SJA1110_HEADER_LEN 4 50 49 #define SJA1110_RX_TRAILER_LEN 13 ··· 189 184 static struct sk_buff *sja1110_xmit(struct sk_buff *skb, 190 185 struct net_device *netdev) 191 186 { 187 + struct sk_buff *clone = SJA1105_SKB_CB(skb)->clone; 192 188 struct dsa_port *dp = dsa_slave_to_port(netdev); 193 189 u16 tx_vid = dsa_8021q_tx_vid(dp->ds, dp->index); 194 190 u16 queue_mapping = skb_get_queue_mapping(skb); ··· 227 221 *tx_trailer = cpu_to_be32(SJA1110_TX_TRAILER_PRIO(pcp) | 228 222 SJA1110_TX_TRAILER_SWITCHID(dp->ds->index) | 229 223 SJA1110_TX_TRAILER_DESTPORTS(BIT(dp->index))); 224 + if (clone) { 225 + u8 ts_id = SJA1105_SKB_CB(clone)->ts_id; 226 + 227 + *tx_header |= htons(SJA1110_TX_HEADER_TAKE_TS); 228 + *tx_trailer |= cpu_to_be32(SJA1110_TX_TRAILER_TSTAMP_ID(ts_id)); 229 + } 230 230 231 231 return skb; 232 232 } ··· 435 423 is_meta); 436 424 } 437 425 426 + static struct sk_buff *sja1110_rcv_meta(struct sk_buff *skb, u16 rx_header) 427 + { 428 + int switch_id = SJA1110_RX_HEADER_SWITCH_ID(rx_header); 429 + int n_ts = SJA1110_RX_HEADER_N_TS(rx_header); 430 + struct net_device *master = skb->dev; 431 + struct dsa_port *cpu_dp; 432 + u8 *buf = skb->data + 2; 433 + struct dsa_switch *ds; 434 + int i; 435 + 436 + cpu_dp = master->dsa_ptr; 437 + ds = dsa_switch_find(cpu_dp->dst->index, switch_id); 438 + if (!ds) { 439 + net_err_ratelimited("%s: cannot find switch id %d\n", 440 + master->name, switch_id); 441 + return NULL; 442 + } 443 + 444 + for (i = 0; i <= n_ts; i++) { 445 + u8 ts_id, source_port, dir; 446 + u64 tstamp; 447 + 448 + ts_id = buf[0]; 449 + source_port = (buf[1] & GENMASK(7, 4)) >> 4; 450 + dir = (buf[1] & BIT(3)) >> 3; 451 + tstamp = be64_to_cpu(*(__be64 *)(buf + 2)); 452 + 453 + sja1110_process_meta_tstamp(ds, source_port, ts_id, dir, 454 + tstamp); 455 + 456 + buf += SJA1110_META_TSTAMP_SIZE; 457 + } 458 + 459 + /* Discard the meta frame, we've consumed the timestamps it contained */ 460 + return NULL; 461 + } 462 + 438 463 static struct sk_buff *sja1110_rcv_inband_control_extension(struct sk_buff *skb, 439 464 int *source_port, 440 465 int *switch_id) ··· 487 438 * comes afterwards. 488 439 */ 489 440 rx_header = ntohs(*(__be16 *)skb->data); 441 + 442 + if (rx_header & SJA1110_RX_HEADER_IS_METADATA) 443 + return sja1110_rcv_meta(skb, rx_header); 490 444 491 445 /* Timestamp frame, we have a trailer */ 492 446 if (rx_header & SJA1110_RX_HEADER_HAS_TRAILER) {