diff options
author | David S. Miller <davem@davemloft.net> | 2018-02-14 14:33:38 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-02-14 14:33:38 -0500 |
commit | 64da58528bdbdba171cf6c6ffaf39c2ee75e3a10 (patch) | |
tree | d779fcb16a984e9c1070269050d885c2d73ce120 /net/dsa/dsa.c | |
parent | e0f9759f530bf789e984961dce79f525b151ecf3 (diff) | |
parent | a2e47134e577713add97124afd812bc3f93627fb (diff) |
Merge branch 'PTP-support-for-DSA-and-mv88e6xxx-driver'
Andrew Lunn says:
====================
PTP support for DSA and mv88e6xxx driver.
This patchset adds support for using the PTP hardware in switches
supported by the mv88e6xxx driver. The code was produces in
collaboration with Brandon Streiff doing the initial implementation,
and then Richard Cochran and Andrew Lunn making further changes and
cleanups.
The code is sufficient to use ptp4l on a single DSA interface, either
as a master or a slave. Due to the use of an MDIO bus to access the
switch, reading hardware timestamps is slower than what ptp4l
expects. Thus it is necessary to use the option
--tx_timestamp_timeout=32. Heavy use of ethtool -S, or bridge fdb show
can also upset ptp4l. Patches to address this will follow.
Further work is requires to support bridges using Boundary Clock or
Transparent Clock mode.
Since the RFC, an overflow bug has been fixed. Brandon Streiff
has also Acked-by: the updates to his initial patchset.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dsa/dsa.c')
-rw-r--r-- | net/dsa/dsa.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 6a9d0f50fbee..e63c554e0623 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/netdevice.h> | 23 | #include <linux/netdevice.h> |
24 | #include <linux/sysfs.h> | 24 | #include <linux/sysfs.h> |
25 | #include <linux/phy_fixed.h> | 25 | #include <linux/phy_fixed.h> |
26 | #include <linux/ptp_classify.h> | ||
26 | #include <linux/gpio/consumer.h> | 27 | #include <linux/gpio/consumer.h> |
27 | #include <linux/etherdevice.h> | 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 | EXPORT_SYMBOL_GPL(dsa_dev_to_net_device); | 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 | static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev, | 158 | static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev, |
126 | struct packet_type *pt, struct net_device *unused) | 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 | s->rx_bytes += skb->len; | 190 | s->rx_bytes += skb->len; |
158 | u64_stats_update_end(&s->syncp); | 191 | u64_stats_update_end(&s->syncp); |
159 | 192 | ||
193 | if (dsa_skb_defer_rx_timestamp(p, skb)) | ||
194 | return 0; | ||
195 | |||
160 | netif_receive_skb(skb); | 196 | netif_receive_skb(skb); |
161 | 197 | ||
162 | return 0; | 198 | return 0; |