diff options
-rw-r--r-- | include/linux/phy.h | 2 | ||||
-rw-r--r-- | include/linux/skbuff.h | 7 | ||||
-rw-r--r-- | net/core/timestamping.c | 12 |
3 files changed, 17 insertions, 4 deletions
diff --git a/include/linux/phy.h b/include/linux/phy.h index 54fc4138955f..79f337c47388 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h | |||
@@ -420,7 +420,7 @@ struct phy_driver { | |||
420 | 420 | ||
421 | /* | 421 | /* |
422 | * Requests a Tx timestamp for 'skb'. The phy driver promises | 422 | * Requests a Tx timestamp for 'skb'. The phy driver promises |
423 | * to deliver it to the socket's error queue as soon as a | 423 | * to deliver it using skb_complete_tx_timestamp() as soon as a |
424 | * timestamp becomes available. One of the PTP_CLASS_ values | 424 | * timestamp becomes available. One of the PTP_CLASS_ values |
425 | * is passed in 'type'. | 425 | * is passed in 'type'. |
426 | */ | 426 | */ |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 8bd383caa363..0f966460a345 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -2020,8 +2020,13 @@ static inline bool skb_defer_rx_timestamp(struct sk_buff *skb) | |||
2020 | /** | 2020 | /** |
2021 | * skb_complete_tx_timestamp() - deliver cloned skb with tx timestamps | 2021 | * skb_complete_tx_timestamp() - deliver cloned skb with tx timestamps |
2022 | * | 2022 | * |
2023 | * PHY drivers may accept clones of transmitted packets for | ||
2024 | * timestamping via their phy_driver.txtstamp method. These drivers | ||
2025 | * must call this function to return the skb back to the stack, with | ||
2026 | * or without a timestamp. | ||
2027 | * | ||
2023 | * @skb: clone of the the original outgoing packet | 2028 | * @skb: clone of the the original outgoing packet |
2024 | * @hwtstamps: hardware time stamps | 2029 | * @hwtstamps: hardware time stamps, may be NULL if not available |
2025 | * | 2030 | * |
2026 | */ | 2031 | */ |
2027 | void skb_complete_tx_timestamp(struct sk_buff *skb, | 2032 | void skb_complete_tx_timestamp(struct sk_buff *skb, |
diff --git a/net/core/timestamping.c b/net/core/timestamping.c index 98a52640e7cd..82fb28857b64 100644 --- a/net/core/timestamping.c +++ b/net/core/timestamping.c | |||
@@ -57,9 +57,13 @@ void skb_clone_tx_timestamp(struct sk_buff *skb) | |||
57 | case PTP_CLASS_V2_VLAN: | 57 | case PTP_CLASS_V2_VLAN: |
58 | phydev = skb->dev->phydev; | 58 | phydev = skb->dev->phydev; |
59 | if (likely(phydev->drv->txtstamp)) { | 59 | if (likely(phydev->drv->txtstamp)) { |
60 | if (!atomic_inc_not_zero(&sk->sk_refcnt)) | ||
61 | return; | ||
60 | clone = skb_clone(skb, GFP_ATOMIC); | 62 | clone = skb_clone(skb, GFP_ATOMIC); |
61 | if (!clone) | 63 | if (!clone) { |
64 | sock_put(sk); | ||
62 | return; | 65 | return; |
66 | } | ||
63 | clone->sk = sk; | 67 | clone->sk = sk; |
64 | phydev->drv->txtstamp(phydev, clone, type); | 68 | phydev->drv->txtstamp(phydev, clone, type); |
65 | } | 69 | } |
@@ -77,8 +81,11 @@ void skb_complete_tx_timestamp(struct sk_buff *skb, | |||
77 | struct sock_exterr_skb *serr; | 81 | struct sock_exterr_skb *serr; |
78 | int err; | 82 | int err; |
79 | 83 | ||
80 | if (!hwtstamps) | 84 | if (!hwtstamps) { |
85 | sock_put(sk); | ||
86 | kfree_skb(skb); | ||
81 | return; | 87 | return; |
88 | } | ||
82 | 89 | ||
83 | *skb_hwtstamps(skb) = *hwtstamps; | 90 | *skb_hwtstamps(skb) = *hwtstamps; |
84 | serr = SKB_EXT_ERR(skb); | 91 | serr = SKB_EXT_ERR(skb); |
@@ -87,6 +94,7 @@ void skb_complete_tx_timestamp(struct sk_buff *skb, | |||
87 | serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; | 94 | serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; |
88 | skb->sk = NULL; | 95 | skb->sk = NULL; |
89 | err = sock_queue_err_skb(sk, skb); | 96 | err = sock_queue_err_skb(sk, skb); |
97 | sock_put(sk); | ||
90 | if (err) | 98 | if (err) |
91 | kfree_skb(skb); | 99 | kfree_skb(skb); |
92 | } | 100 | } |