162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * PTP 1588 clock support - support for timestamping in PHY devices 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2010 OMICRON electronics GmbH 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#include <linux/errqueue.h> 862306a36Sopenharmony_ci#include <linux/phy.h> 962306a36Sopenharmony_ci#include <linux/ptp_classify.h> 1062306a36Sopenharmony_ci#include <linux/skbuff.h> 1162306a36Sopenharmony_ci#include <linux/export.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic unsigned int classify(const struct sk_buff *skb) 1462306a36Sopenharmony_ci{ 1562306a36Sopenharmony_ci if (likely(skb->dev && skb->dev->phydev && 1662306a36Sopenharmony_ci skb->dev->phydev->mii_ts)) 1762306a36Sopenharmony_ci return ptp_classify_raw(skb); 1862306a36Sopenharmony_ci else 1962306a36Sopenharmony_ci return PTP_CLASS_NONE; 2062306a36Sopenharmony_ci} 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_civoid skb_clone_tx_timestamp(struct sk_buff *skb) 2362306a36Sopenharmony_ci{ 2462306a36Sopenharmony_ci struct mii_timestamper *mii_ts; 2562306a36Sopenharmony_ci struct sk_buff *clone; 2662306a36Sopenharmony_ci unsigned int type; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci if (!skb->sk) 2962306a36Sopenharmony_ci return; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci type = classify(skb); 3262306a36Sopenharmony_ci if (type == PTP_CLASS_NONE) 3362306a36Sopenharmony_ci return; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci mii_ts = skb->dev->phydev->mii_ts; 3662306a36Sopenharmony_ci if (likely(mii_ts->txtstamp)) { 3762306a36Sopenharmony_ci clone = skb_clone_sk(skb); 3862306a36Sopenharmony_ci if (!clone) 3962306a36Sopenharmony_ci return; 4062306a36Sopenharmony_ci mii_ts->txtstamp(mii_ts, clone, type); 4162306a36Sopenharmony_ci } 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_clone_tx_timestamp); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cibool skb_defer_rx_timestamp(struct sk_buff *skb) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci struct mii_timestamper *mii_ts; 4862306a36Sopenharmony_ci unsigned int type; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci if (!skb->dev || !skb->dev->phydev || !skb->dev->phydev->mii_ts) 5162306a36Sopenharmony_ci return false; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci if (skb_headroom(skb) < ETH_HLEN) 5462306a36Sopenharmony_ci return false; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci __skb_push(skb, ETH_HLEN); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci type = ptp_classify_raw(skb); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci __skb_pull(skb, ETH_HLEN); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci if (type == PTP_CLASS_NONE) 6362306a36Sopenharmony_ci return false; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci mii_ts = skb->dev->phydev->mii_ts; 6662306a36Sopenharmony_ci if (likely(mii_ts->rxtstamp)) 6762306a36Sopenharmony_ci return mii_ts->rxtstamp(mii_ts, skb, type); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci return false; 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_defer_rx_timestamp); 72