blob: 04840697fe79fa5e1f4e2908cac8cb8ad13ffc40 [file] [log] [blame]
Thomas Gleixner74ba9202019-05-20 09:19:02 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Richard Cochranc1f19b52010-07-17 08:49:36 +00002/*
3 * PTP 1588 clock support - support for timestamping in PHY devices
4 *
5 * Copyright (C) 2010 OMICRON electronics GmbH
Richard Cochranc1f19b52010-07-17 08:49:36 +00006 */
7#include <linux/errqueue.h>
8#include <linux/phy.h>
9#include <linux/ptp_classify.h>
10#include <linux/skbuff.h>
Paul Gortmakerbc3b2d72011-07-15 11:47:34 -040011#include <linux/export.h>
Richard Cochranc1f19b52010-07-17 08:49:36 +000012
Eric Dumazet62ab0812010-12-06 20:50:09 +000013static unsigned int classify(const struct sk_buff *skb)
Richard Cochranc1f19b52010-07-17 08:49:36 +000014{
Daniel Borkmanne62d2df2014-03-28 18:58:21 +010015 if (likely(skb->dev && skb->dev->phydev &&
Richard Cochran4715f652019-12-25 18:16:15 -080016 skb->dev->phydev->mii_ts))
Daniel Borkmann164d8c62014-03-28 18:58:22 +010017 return ptp_classify_raw(skb);
Richard Cochranc1f19b52010-07-17 08:49:36 +000018 else
19 return PTP_CLASS_NONE;
20}
21
22void skb_clone_tx_timestamp(struct sk_buff *skb)
23{
Richard Cochran4715f652019-12-25 18:16:15 -080024 struct mii_timestamper *mii_ts;
Richard Cochranc1f19b52010-07-17 08:49:36 +000025 struct sk_buff *clone;
Richard Cochranc1f19b52010-07-17 08:49:36 +000026 unsigned int type;
27
Alexander Duyck62bccb82014-09-04 13:31:35 -040028 if (!skb->sk)
Richard Cochranc1f19b52010-07-17 08:49:36 +000029 return;
30
31 type = classify(skb);
Stefan Sørensenb9c701e2014-06-27 11:59:09 +020032 if (type == PTP_CLASS_NONE)
33 return;
Richard Cochranc1f19b52010-07-17 08:49:36 +000034
Richard Cochran4715f652019-12-25 18:16:15 -080035 mii_ts = skb->dev->phydev->mii_ts;
36 if (likely(mii_ts->txtstamp)) {
Alexander Duyck62bccb82014-09-04 13:31:35 -040037 clone = skb_clone_sk(skb);
38 if (!clone)
Stefan Sørensenb9c701e2014-06-27 11:59:09 +020039 return;
Richard Cochran4715f652019-12-25 18:16:15 -080040 mii_ts->txtstamp(mii_ts, clone, type);
Richard Cochranc1f19b52010-07-17 08:49:36 +000041 }
42}
Richard Cochran1c172162011-06-12 02:18:58 +000043EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp);
Richard Cochranc1f19b52010-07-17 08:49:36 +000044
Richard Cochranc1f19b52010-07-17 08:49:36 +000045bool skb_defer_rx_timestamp(struct sk_buff *skb)
46{
Richard Cochran4715f652019-12-25 18:16:15 -080047 struct mii_timestamper *mii_ts;
Richard Cochranc1f19b52010-07-17 08:49:36 +000048 unsigned int type;
49
Richard Cochran4715f652019-12-25 18:16:15 -080050 if (!skb->dev || !skb->dev->phydev || !skb->dev->phydev->mii_ts)
Alexander Duyck1007f592015-07-09 11:02:52 -070051 return false;
52
Eric Dumazeta19faf02010-12-05 18:50:32 +000053 if (skb_headroom(skb) < ETH_HLEN)
54 return false;
Alexander Duyck1007f592015-07-09 11:02:52 -070055
Eric Dumazeta19faf02010-12-05 18:50:32 +000056 __skb_push(skb, ETH_HLEN);
Richard Cochranc1f19b52010-07-17 08:49:36 +000057
Alexander Duyck1007f592015-07-09 11:02:52 -070058 type = ptp_classify_raw(skb);
Richard Cochranc1f19b52010-07-17 08:49:36 +000059
Eric Dumazeta19faf02010-12-05 18:50:32 +000060 __skb_pull(skb, ETH_HLEN);
Richard Cochranc1f19b52010-07-17 08:49:36 +000061
Stefan Sørensenb9c701e2014-06-27 11:59:09 +020062 if (type == PTP_CLASS_NONE)
63 return false;
64
Richard Cochran4715f652019-12-25 18:16:15 -080065 mii_ts = skb->dev->phydev->mii_ts;
66 if (likely(mii_ts->rxtstamp))
67 return mii_ts->rxtstamp(mii_ts, skb, type);
Richard Cochranc1f19b52010-07-17 08:49:36 +000068
69 return false;
70}
Richard Cochran238442f2011-06-19 21:51:23 +000071EXPORT_SYMBOL_GPL(skb_defer_rx_timestamp);