timestamping.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. static struct sock_filter ptp_filter[] = {
  25. PTP_FILTER
  26. };
  27. static unsigned int classify(const struct sk_buff *skb)
  28. {
  29. if (likely(skb->dev &&
  30. skb->dev->phydev &&
  31. skb->dev->phydev->drv))
  32. return sk_run_filter(skb, ptp_filter);
  33. else
  34. return PTP_CLASS_NONE;
  35. }
  36. void skb_clone_tx_timestamp(struct sk_buff *skb)
  37. {
  38. struct phy_device *phydev;
  39. struct sk_buff *clone;
  40. struct sock *sk = skb->sk;
  41. unsigned int type;
  42. if (!sk)
  43. return;
  44. type = classify(skb);
  45. switch (type) {
  46. case PTP_CLASS_V1_IPV4:
  47. case PTP_CLASS_V1_IPV6:
  48. case PTP_CLASS_V2_IPV4:
  49. case PTP_CLASS_V2_IPV6:
  50. case PTP_CLASS_V2_L2:
  51. case PTP_CLASS_V2_VLAN:
  52. phydev = skb->dev->phydev;
  53. if (likely(phydev->drv->txtstamp)) {
  54. clone = skb_clone(skb, GFP_ATOMIC);
  55. if (!clone)
  56. return;
  57. clone->sk = sk;
  58. phydev->drv->txtstamp(phydev, clone, type);
  59. }
  60. break;
  61. default:
  62. break;
  63. }
  64. }
  65. EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp);
  66. void skb_complete_tx_timestamp(struct sk_buff *skb,
  67. struct skb_shared_hwtstamps *hwtstamps)
  68. {
  69. struct sock *sk = skb->sk;
  70. struct sock_exterr_skb *serr;
  71. int err;
  72. if (!hwtstamps)
  73. return;
  74. *skb_hwtstamps(skb) = *hwtstamps;
  75. serr = SKB_EXT_ERR(skb);
  76. memset(serr, 0, sizeof(*serr));
  77. serr->ee.ee_errno = ENOMSG;
  78. serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
  79. skb->sk = NULL;
  80. err = sock_queue_err_skb(sk, skb);
  81. if (err)
  82. kfree_skb(skb);
  83. }
  84. EXPORT_SYMBOL_GPL(skb_complete_tx_timestamp);
  85. bool skb_defer_rx_timestamp(struct sk_buff *skb)
  86. {
  87. struct phy_device *phydev;
  88. unsigned int type;
  89. if (skb_headroom(skb) < ETH_HLEN)
  90. return false;
  91. __skb_push(skb, ETH_HLEN);
  92. type = classify(skb);
  93. __skb_pull(skb, ETH_HLEN);
  94. switch (type) {
  95. case PTP_CLASS_V1_IPV4:
  96. case PTP_CLASS_V1_IPV6:
  97. case PTP_CLASS_V2_IPV4:
  98. case PTP_CLASS_V2_IPV6:
  99. case PTP_CLASS_V2_L2:
  100. case PTP_CLASS_V2_VLAN:
  101. phydev = skb->dev->phydev;
  102. if (likely(phydev->drv->rxtstamp))
  103. return phydev->drv->rxtstamp(phydev, skb, type);
  104. break;
  105. default:
  106. break;
  107. }
  108. return false;
  109. }
  110. EXPORT_SYMBOL_GPL(skb_defer_rx_timestamp);
  111. void __init skb_timestamping_init(void)
  112. {
  113. BUG_ON(sk_chk_filter(ptp_filter, ARRAY_SIZE(ptp_filter)));
  114. }