|
23 | 23 | #include <linux/netdevice.h> |
24 | 24 | #include <linux/sysfs.h> |
25 | 25 | #include <linux/phy_fixed.h> |
| 26 | +#include <linux/ptp_classify.h> |
26 | 27 | #include <linux/gpio/consumer.h> |
27 | 28 | #include <linux/etherdevice.h> |
28 | 29 |
|
@@ -122,6 +123,38 @@ struct net_device *dsa_dev_to_net_device(struct device *dev) |
122 | 123 | } |
123 | 124 | EXPORT_SYMBOL_GPL(dsa_dev_to_net_device); |
124 | 125 |
|
| 126 | +/* Determine if we should defer delivery of skb until we have a rx timestamp. |
| 127 | + * |
| 128 | + * Called from dsa_switch_rcv. For now, this will only work if tagging is |
| 129 | + * enabled on the switch. Normally the MAC driver would retrieve the hardware |
| 130 | + * timestamp when it reads the packet out of the hardware. However in a DSA |
| 131 | + * switch, the DSA driver owning the interface to which the packet is |
| 132 | + * delivered is never notified unless we do so here. |
| 133 | + */ |
| 134 | +static bool dsa_skb_defer_rx_timestamp(struct dsa_slave_priv *p, |
| 135 | + struct sk_buff *skb) |
| 136 | +{ |
| 137 | + struct dsa_switch *ds = p->dp->ds; |
| 138 | + unsigned int type; |
| 139 | + |
| 140 | + if (skb_headroom(skb) < ETH_HLEN) |
| 141 | + return false; |
| 142 | + |
| 143 | + __skb_push(skb, ETH_HLEN); |
| 144 | + |
| 145 | + type = ptp_classify_raw(skb); |
| 146 | + |
| 147 | + __skb_pull(skb, ETH_HLEN); |
| 148 | + |
| 149 | + if (type == PTP_CLASS_NONE) |
| 150 | + return false; |
| 151 | + |
| 152 | + if (likely(ds->ops->port_rxtstamp)) |
| 153 | + return ds->ops->port_rxtstamp(ds, p->dp->index, skb, type); |
| 154 | + |
| 155 | + return false; |
| 156 | +} |
| 157 | + |
125 | 158 | static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev, |
126 | 159 | struct packet_type *pt, struct net_device *unused) |
127 | 160 | { |
@@ -157,6 +190,9 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev, |
157 | 190 | s->rx_bytes += skb->len; |
158 | 191 | u64_stats_update_end(&s->syncp); |
159 | 192 |
|
| 193 | + if (dsa_skb_defer_rx_timestamp(p, skb)) |
| 194 | + return 0; |
| 195 | + |
160 | 196 | netif_receive_skb(skb); |
161 | 197 |
|
162 | 198 | return 0; |
|
0 commit comments