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