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 | } |
