Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / net / core / timestamping.c
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->drv))
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 phy_device *phydev;
25         struct sk_buff *clone;
26         unsigned int type;
27
28         if (!skb->sk)
29                 return;
30
31         type = classify(skb);
32         if (type == PTP_CLASS_NONE)
33                 return;
34
35         phydev = skb->dev->phydev;
36         if (likely(phydev->drv->txtstamp)) {
37                 clone = skb_clone_sk(skb);
38                 if (!clone)
39                         return;
40                 phydev->drv->txtstamp(phydev, clone, type);
41         }
42 }
43 EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp);
44
45 bool skb_defer_rx_timestamp(struct sk_buff *skb)
46 {
47         struct phy_device *phydev;
48         unsigned int type;
49
50         if (!skb->dev || !skb->dev->phydev || !skb->dev->phydev->drv)
51                 return false;
52
53         if (skb_headroom(skb) < ETH_HLEN)
54                 return false;
55
56         __skb_push(skb, ETH_HLEN);
57
58         type = ptp_classify_raw(skb);
59
60         __skb_pull(skb, ETH_HLEN);
61
62         if (type == PTP_CLASS_NONE)
63                 return false;
64
65         phydev = skb->dev->phydev;
66         if (likely(phydev->drv->rxtstamp))
67                 return phydev->drv->rxtstamp(phydev, skb, type);
68
69         return false;
70 }
71 EXPORT_SYMBOL_GPL(skb_defer_rx_timestamp);