blob: 7911235706a978a87f9eee2d6e89f20d3755f209 [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 Cochranc1f19b52010-07-17 08:49:36 +000016 skb->dev->phydev->drv))
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{
24 struct phy_device *phydev;
25 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
Stefan Sørensenb9c701e2014-06-27 11:59:09 +020035 phydev = skb->dev->phydev;
36 if (likely(phydev->drv->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;
Stefan Sørensenb9c701e2014-06-27 11:59:09 +020040 phydev->drv->txtstamp(phydev, 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{
47 struct phy_device *phydev;
48 unsigned int type;
49
Alexander Duyck1007f592015-07-09 11:02:52 -070050 if (!skb->dev || !skb->dev->phydev || !skb->dev->phydev->drv)
51 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
65 phydev = skb->dev->phydev;
66 if (likely(phydev->drv->rxtstamp))
67 return phydev->drv->rxtstamp(phydev, 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);