174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2c1f19b51SRichard Cochran /* 3c1f19b51SRichard Cochran * PTP 1588 clock support - support for timestamping in PHY devices 4c1f19b51SRichard Cochran * 5c1f19b51SRichard Cochran * Copyright (C) 2010 OMICRON electronics GmbH 6c1f19b51SRichard Cochran */ 7c1f19b51SRichard Cochran #include <linux/errqueue.h> 8c1f19b51SRichard Cochran #include <linux/phy.h> 9c1f19b51SRichard Cochran #include <linux/ptp_classify.h> 10c1f19b51SRichard Cochran #include <linux/skbuff.h> 11bc3b2d7fSPaul Gortmaker #include <linux/export.h> 12c1f19b51SRichard Cochran 1362ab0812SEric Dumazet static unsigned int classify(const struct sk_buff *skb) 14c1f19b51SRichard Cochran { 15e62d2df0SDaniel Borkmann if (likely(skb->dev && skb->dev->phydev && 164715f65fSRichard Cochran skb->dev->phydev->mii_ts)) 17164d8c66SDaniel Borkmann return ptp_classify_raw(skb); 18c1f19b51SRichard Cochran else 19c1f19b51SRichard Cochran return PTP_CLASS_NONE; 20c1f19b51SRichard Cochran } 21c1f19b51SRichard Cochran 22c1f19b51SRichard Cochran void skb_clone_tx_timestamp(struct sk_buff *skb) 23c1f19b51SRichard Cochran { 244715f65fSRichard Cochran struct mii_timestamper *mii_ts; 25c1f19b51SRichard Cochran struct sk_buff *clone; 26c1f19b51SRichard Cochran unsigned int type; 27c1f19b51SRichard Cochran 28*2dd35600SKory Maincent if (!skb->sk || !skb->dev || 29*2dd35600SKory Maincent !phy_is_default_hwtstamp(skb->dev->phydev)) 30c1f19b51SRichard Cochran return; 31c1f19b51SRichard Cochran 32c1f19b51SRichard Cochran type = classify(skb); 33b9c701edSStefan Sørensen if (type == PTP_CLASS_NONE) 34b9c701edSStefan Sørensen return; 35c1f19b51SRichard Cochran 364715f65fSRichard Cochran mii_ts = skb->dev->phydev->mii_ts; 374715f65fSRichard Cochran if (likely(mii_ts->txtstamp)) { 3862bccb8cSAlexander Duyck clone = skb_clone_sk(skb); 3962bccb8cSAlexander Duyck if (!clone) 40c1f19b51SRichard Cochran return; 414715f65fSRichard Cochran mii_ts->txtstamp(mii_ts, clone, type); 42c1f19b51SRichard Cochran } 43c1f19b51SRichard Cochran } 441c17216eSRichard Cochran EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp); 45c1f19b51SRichard Cochran 46c1f19b51SRichard Cochran bool skb_defer_rx_timestamp(struct sk_buff *skb) 47c1f19b51SRichard Cochran { 484715f65fSRichard Cochran struct mii_timestamper *mii_ts; 49c1f19b51SRichard Cochran unsigned int type; 50c1f19b51SRichard Cochran 51*2dd35600SKory Maincent if (!skb->dev || !phy_is_default_hwtstamp(skb->dev->phydev)) 521007f59dSAlexander Duyck return false; 531007f59dSAlexander Duyck 54a19faf02SEric Dumazet if (skb_headroom(skb) < ETH_HLEN) 55a19faf02SEric Dumazet return false; 561007f59dSAlexander Duyck 57a19faf02SEric Dumazet __skb_push(skb, ETH_HLEN); 58c1f19b51SRichard Cochran 591007f59dSAlexander Duyck type = ptp_classify_raw(skb); 60c1f19b51SRichard Cochran 61a19faf02SEric Dumazet __skb_pull(skb, ETH_HLEN); 62c1f19b51SRichard Cochran 63b9c701edSStefan Sørensen if (type == PTP_CLASS_NONE) 64b9c701edSStefan Sørensen return false; 65b9c701edSStefan Sørensen 664715f65fSRichard Cochran mii_ts = skb->dev->phydev->mii_ts; 674715f65fSRichard Cochran if (likely(mii_ts->rxtstamp)) 684715f65fSRichard Cochran return mii_ts->rxtstamp(mii_ts, skb, type); 69c1f19b51SRichard Cochran 70c1f19b51SRichard Cochran return false; 71c1f19b51SRichard Cochran } 72238442f6SRichard Cochran EXPORT_SYMBOL_GPL(skb_defer_rx_timestamp); 73