timestamping.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. #include <linux/ptp_clock_kernel.h>
  13. static unsigned int classify(const struct sk_buff *skb)
  14. {
  15. if (likely(skb->dev && skb->dev->phydev &&
  16. skb->dev->phydev->mii_ts))
  17. return ptp_classify_raw(skb);
  18. else
  19. return PTP_CLASS_NONE;
  20. }
  21. void skb_clone_tx_timestamp(struct sk_buff *skb)
  22. {
  23. struct hwtstamp_provider *hwprov;
  24. struct mii_timestamper *mii_ts;
  25. struct phy_device *phydev;
  26. struct sk_buff *clone;
  27. unsigned int type;
  28. if (!skb->sk || !skb->dev)
  29. return;
  30. rcu_read_lock();
  31. hwprov = rcu_dereference(skb->dev->hwprov);
  32. if (hwprov) {
  33. if (hwprov->source != HWTSTAMP_SOURCE_PHYLIB ||
  34. !hwprov->phydev) {
  35. rcu_read_unlock();
  36. return;
  37. }
  38. phydev = hwprov->phydev;
  39. } else {
  40. phydev = skb->dev->phydev;
  41. if (!phy_is_default_hwtstamp(phydev)) {
  42. rcu_read_unlock();
  43. return;
  44. }
  45. }
  46. rcu_read_unlock();
  47. type = classify(skb);
  48. if (type == PTP_CLASS_NONE)
  49. return;
  50. mii_ts = phydev->mii_ts;
  51. if (likely(mii_ts->txtstamp)) {
  52. clone = skb_clone_sk(skb);
  53. if (!clone)
  54. return;
  55. mii_ts->txtstamp(mii_ts, clone, type);
  56. }
  57. }
  58. EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp);
  59. bool skb_defer_rx_timestamp(struct sk_buff *skb)
  60. {
  61. struct hwtstamp_provider *hwprov;
  62. struct mii_timestamper *mii_ts;
  63. struct phy_device *phydev;
  64. unsigned int type;
  65. if (!skb->dev)
  66. return false;
  67. rcu_read_lock();
  68. hwprov = rcu_dereference(skb->dev->hwprov);
  69. if (hwprov) {
  70. if (hwprov->source != HWTSTAMP_SOURCE_PHYLIB ||
  71. !hwprov->phydev) {
  72. rcu_read_unlock();
  73. return false;
  74. }
  75. phydev = hwprov->phydev;
  76. } else {
  77. phydev = skb->dev->phydev;
  78. if (!phy_is_default_hwtstamp(phydev)) {
  79. rcu_read_unlock();
  80. return false;
  81. }
  82. }
  83. rcu_read_unlock();
  84. if (skb_headroom(skb) < ETH_HLEN)
  85. return false;
  86. __skb_push(skb, ETH_HLEN);
  87. type = ptp_classify_raw(skb);
  88. __skb_pull(skb, ETH_HLEN);
  89. if (type == PTP_CLASS_NONE)
  90. return false;
  91. mii_ts = phydev->mii_ts;
  92. if (likely(mii_ts->rxtstamp))
  93. return mii_ts->rxtstamp(mii_ts, skb, type);
  94. return false;
  95. }
  96. EXPORT_SYMBOL_GPL(skb_defer_rx_timestamp);