xref: /linux/net/core/timestamping.c (revision a36e9f5cfe9eb3a1dce8769c7058251c42705357)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * PTP 1588 clock support - support for timestamping in PHY devices
4  *
5  * Copyright (C) 2010 OMICRON electronics GmbH
6  */
7 #include <linux/errqueue.h>
8 #include <linux/phy.h>
9 #include <linux/ptp_classify.h>
10 #include <linux/skbuff.h>
11 #include <linux/export.h>
12 
13 static unsigned int classify(const struct sk_buff *skb)
14 {
15 	if (likely(skb->dev && skb->dev->phydev &&
16 		   skb->dev->phydev->mii_ts))
17 		return ptp_classify_raw(skb);
18 	else
19 		return PTP_CLASS_NONE;
20 }
21 
22 void skb_clone_tx_timestamp(struct sk_buff *skb)
23 {
24 	struct mii_timestamper *mii_ts;
25 	struct sk_buff *clone;
26 	unsigned int type;
27 
28 	if (!skb->sk || !skb->dev ||
29 	    !phy_is_default_hwtstamp(skb->dev->phydev))
30 		return;
31 
32 	type = classify(skb);
33 	if (type == PTP_CLASS_NONE)
34 		return;
35 
36 	mii_ts = skb->dev->phydev->mii_ts;
37 	if (likely(mii_ts->txtstamp)) {
38 		clone = skb_clone_sk(skb);
39 		if (!clone)
40 			return;
41 		mii_ts->txtstamp(mii_ts, clone, type);
42 	}
43 }
44 EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp);
45 
46 bool skb_defer_rx_timestamp(struct sk_buff *skb)
47 {
48 	struct mii_timestamper *mii_ts;
49 	unsigned int type;
50 
51 	if (!skb->dev || !phy_is_default_hwtstamp(skb->dev->phydev))
52 		return false;
53 
54 	if (skb_headroom(skb) < ETH_HLEN)
55 		return false;
56 
57 	__skb_push(skb, ETH_HLEN);
58 
59 	type = ptp_classify_raw(skb);
60 
61 	__skb_pull(skb, ETH_HLEN);
62 
63 	if (type == PTP_CLASS_NONE)
64 		return false;
65 
66 	mii_ts = skb->dev->phydev->mii_ts;
67 	if (likely(mii_ts->rxtstamp))
68 		return mii_ts->rxtstamp(mii_ts, skb, type);
69 
70 	return false;
71 }
72 EXPORT_SYMBOL_GPL(skb_defer_rx_timestamp);
73