timestamping.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*
  2. * PTP 1588 clock support - support for timestamping in PHY devices
  3. *
  4. * Copyright (C) 2010 OMICRON electronics GmbH
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20. #include <linux/errqueue.h>
  21. #include <linux/phy.h>
  22. #include <linux/ptp_classify.h>
  23. #include <linux/skbuff.h>
  24. #include <linux/export.h>
  25. static unsigned int classify(const struct sk_buff *skb)
  26. {
  27. if (likely(skb->dev && skb->dev->phydev &&
  28. skb->dev->phydev->drv))
  29. return ptp_classify_raw(skb);
  30. else
  31. return PTP_CLASS_NONE;
  32. }
  33. void skb_clone_tx_timestamp(struct sk_buff *skb)
  34. {
  35. struct phy_device *phydev;
  36. struct sk_buff *clone;
  37. struct sock *sk = skb->sk;
  38. unsigned int type;
  39. if (!sk)
  40. return;
  41. type = classify(skb);
  42. switch (type) {
  43. case PTP_CLASS_V1_IPV4:
  44. case PTP_CLASS_V1_IPV6:
  45. case PTP_CLASS_V2_IPV4:
  46. case PTP_CLASS_V2_IPV6:
  47. case PTP_CLASS_V2_L2:
  48. case PTP_CLASS_V2_VLAN:
  49. phydev = skb->dev->phydev;
  50. if (likely(phydev->drv->txtstamp)) {
  51. if (!atomic_inc_not_zero(&sk->sk_refcnt))
  52. return;
  53. clone = skb_clone(skb, GFP_ATOMIC);
  54. if (!clone) {
  55. sock_put(sk);
  56. return;
  57. }
  58. clone->sk = sk;
  59. phydev->drv->txtstamp(phydev, clone, type);
  60. }
  61. break;
  62. default:
  63. break;
  64. }
  65. }
  66. EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp);
  67. void skb_complete_tx_timestamp(struct sk_buff *skb,
  68. struct skb_shared_hwtstamps *hwtstamps)
  69. {
  70. struct sock *sk = skb->sk;
  71. struct sock_exterr_skb *serr;
  72. int err;
  73. if (!hwtstamps) {
  74. sock_put(sk);
  75. kfree_skb(skb);
  76. return;
  77. }
  78. *skb_hwtstamps(skb) = *hwtstamps;
  79. serr = SKB_EXT_ERR(skb);
  80. memset(serr, 0, sizeof(*serr));
  81. serr->ee.ee_errno = ENOMSG;
  82. serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
  83. skb->sk = NULL;
  84. err = sock_queue_err_skb(sk, skb);
  85. sock_put(sk);
  86. if (err)
  87. kfree_skb(skb);
  88. }
  89. EXPORT_SYMBOL_GPL(skb_complete_tx_timestamp);
  90. bool skb_defer_rx_timestamp(struct sk_buff *skb)
  91. {
  92. struct phy_device *phydev;
  93. unsigned int type;
  94. if (skb_headroom(skb) < ETH_HLEN)
  95. return false;
  96. __skb_push(skb, ETH_HLEN);
  97. type = classify(skb);
  98. __skb_pull(skb, ETH_HLEN);
  99. switch (type) {
  100. case PTP_CLASS_V1_IPV4:
  101. case PTP_CLASS_V1_IPV6:
  102. case PTP_CLASS_V2_IPV4:
  103. case PTP_CLASS_V2_IPV6:
  104. case PTP_CLASS_V2_L2:
  105. case PTP_CLASS_V2_VLAN:
  106. phydev = skb->dev->phydev;
  107. if (likely(phydev->drv->rxtstamp))
  108. return phydev->drv->rxtstamp(phydev, skb, type);
  109. break;
  110. default:
  111. break;
  112. }
  113. return false;
  114. }
  115. EXPORT_SYMBOL_GPL(skb_defer_rx_timestamp);