xref: /linux/net/core/timestamping.c (revision c797ce168930ce3d62a9b7fc4d7040963ee6a01e)
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 	enum timestamping_layer ts_layer;
25 	struct mii_timestamper *mii_ts;
26 	struct sk_buff *clone;
27 	unsigned int type;
28 
29 	if (!skb->sk)
30 		return;
31 
32 	ts_layer = skb->dev->ts_layer;
33 	if (ts_layer != PHY_TIMESTAMPING)
34 		return;
35 
36 	type = classify(skb);
37 	if (type == PTP_CLASS_NONE)
38 		return;
39 
40 	mii_ts = skb->dev->phydev->mii_ts;
41 	if (likely(mii_ts->txtstamp)) {
42 		clone = skb_clone_sk(skb);
43 		if (!clone)
44 			return;
45 		mii_ts->txtstamp(mii_ts, clone, type);
46 	}
47 }
48 EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp);
49 
50 bool skb_defer_rx_timestamp(struct sk_buff *skb)
51 {
52 	enum timestamping_layer ts_layer;
53 	struct mii_timestamper *mii_ts;
54 	unsigned int type;
55 
56 	if (!skb->dev || !skb->dev->phydev || !skb->dev->phydev->mii_ts)
57 		return false;
58 
59 	ts_layer = skb->dev->ts_layer;
60 	if (ts_layer != PHY_TIMESTAMPING)
61 		return false;
62 
63 	if (skb_headroom(skb) < ETH_HLEN)
64 		return false;
65 
66 	__skb_push(skb, ETH_HLEN);
67 
68 	type = ptp_classify_raw(skb);
69 
70 	__skb_pull(skb, ETH_HLEN);
71 
72 	if (type == PTP_CLASS_NONE)
73 		return false;
74 
75 	mii_ts = skb->dev->phydev->mii_ts;
76 	if (likely(mii_ts->rxtstamp))
77 		return mii_ts->rxtstamp(mii_ts, skb, type);
78 
79 	return false;
80 }
81 EXPORT_SYMBOL_GPL(skb_defer_rx_timestamp);
82