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); 72