xref: /linux/net/core/timestamping.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2c1f19b51SRichard Cochran /*
3c1f19b51SRichard Cochran  * PTP 1588 clock support - support for timestamping in PHY devices
4c1f19b51SRichard Cochran  *
5c1f19b51SRichard Cochran  * Copyright (C) 2010 OMICRON electronics GmbH
6c1f19b51SRichard Cochran  */
7c1f19b51SRichard Cochran #include <linux/errqueue.h>
8c1f19b51SRichard Cochran #include <linux/phy.h>
9c1f19b51SRichard Cochran #include <linux/ptp_classify.h>
10c1f19b51SRichard Cochran #include <linux/skbuff.h>
11bc3b2d7fSPaul Gortmaker #include <linux/export.h>
12c1f19b51SRichard Cochran 
classify(const struct sk_buff * skb)1362ab0812SEric Dumazet static unsigned int classify(const struct sk_buff *skb)
14c1f19b51SRichard Cochran {
15e62d2df0SDaniel Borkmann 	if (likely(skb->dev && skb->dev->phydev &&
164715f65fSRichard Cochran 		   skb->dev->phydev->mii_ts))
17164d8c66SDaniel Borkmann 		return ptp_classify_raw(skb);
18c1f19b51SRichard Cochran 	else
19c1f19b51SRichard Cochran 		return PTP_CLASS_NONE;
20c1f19b51SRichard Cochran }
21c1f19b51SRichard Cochran 
skb_clone_tx_timestamp(struct sk_buff * skb)22c1f19b51SRichard Cochran void skb_clone_tx_timestamp(struct sk_buff *skb)
23c1f19b51SRichard Cochran {
244715f65fSRichard Cochran 	struct mii_timestamper *mii_ts;
25c1f19b51SRichard Cochran 	struct sk_buff *clone;
26c1f19b51SRichard Cochran 	unsigned int type;
27c1f19b51SRichard Cochran 
28*2dd35600SKory Maincent 	if (!skb->sk || !skb->dev ||
29*2dd35600SKory Maincent 	    !phy_is_default_hwtstamp(skb->dev->phydev))
30c1f19b51SRichard Cochran 		return;
31c1f19b51SRichard Cochran 
32c1f19b51SRichard Cochran 	type = classify(skb);
33b9c701edSStefan Sørensen 	if (type == PTP_CLASS_NONE)
34b9c701edSStefan Sørensen 		return;
35c1f19b51SRichard Cochran 
364715f65fSRichard Cochran 	mii_ts = skb->dev->phydev->mii_ts;
374715f65fSRichard Cochran 	if (likely(mii_ts->txtstamp)) {
3862bccb8cSAlexander Duyck 		clone = skb_clone_sk(skb);
3962bccb8cSAlexander Duyck 		if (!clone)
40c1f19b51SRichard Cochran 			return;
414715f65fSRichard Cochran 		mii_ts->txtstamp(mii_ts, clone, type);
42c1f19b51SRichard Cochran 	}
43c1f19b51SRichard Cochran }
441c17216eSRichard Cochran EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp);
45c1f19b51SRichard Cochran 
skb_defer_rx_timestamp(struct sk_buff * skb)46c1f19b51SRichard Cochran bool skb_defer_rx_timestamp(struct sk_buff *skb)
47c1f19b51SRichard Cochran {
484715f65fSRichard Cochran 	struct mii_timestamper *mii_ts;
49c1f19b51SRichard Cochran 	unsigned int type;
50c1f19b51SRichard Cochran 
51*2dd35600SKory Maincent 	if (!skb->dev || !phy_is_default_hwtstamp(skb->dev->phydev))
521007f59dSAlexander Duyck 		return false;
531007f59dSAlexander Duyck 
54a19faf02SEric Dumazet 	if (skb_headroom(skb) < ETH_HLEN)
55a19faf02SEric Dumazet 		return false;
561007f59dSAlexander Duyck 
57a19faf02SEric Dumazet 	__skb_push(skb, ETH_HLEN);
58c1f19b51SRichard Cochran 
591007f59dSAlexander Duyck 	type = ptp_classify_raw(skb);
60c1f19b51SRichard Cochran 
61a19faf02SEric Dumazet 	__skb_pull(skb, ETH_HLEN);
62c1f19b51SRichard Cochran 
63b9c701edSStefan Sørensen 	if (type == PTP_CLASS_NONE)
64b9c701edSStefan Sørensen 		return false;
65b9c701edSStefan Sørensen 
664715f65fSRichard Cochran 	mii_ts = skb->dev->phydev->mii_ts;
674715f65fSRichard Cochran 	if (likely(mii_ts->rxtstamp))
684715f65fSRichard Cochran 		return mii_ts->rxtstamp(mii_ts, skb, type);
69c1f19b51SRichard Cochran 
70c1f19b51SRichard Cochran 	return false;
71c1f19b51SRichard Cochran }
72238442f6SRichard Cochran EXPORT_SYMBOL_GPL(skb_defer_rx_timestamp);
73