mirror of
https://github.com/torvalds/linux.git
synced 2024-11-30 08:01:59 +00:00
Merge branch 'timestamping'
Alexander Duyck says: ==================== This change makes it so that the core path for the phy timestamping logic is shared between skb_tx_tstamp and skb_complete_tx_timestamp. In addition it provides a means of using the same skb clone type path in non phy timestamping drivers. The main motivation for this is to enable non-phy drivers to be able to manipulate tx timestamp skbs for such things as putting them in lists or setting aside buffer in the context block. v2: Incorporated suggested changes from Willem de Bruijn and Eric Dumazet dropped uneeded comment restored order of hwtstamp vs swtstamp added destructor for skb Dropped usage of skb_complete_tx_timestamp as a kfree_skb w/ destructor v3: Updated destructor handling and dealt with socket reference counting issues v4: Split out combining destructors into a separate patch ====================
This commit is contained in:
commit
2c048e6462
@ -1148,7 +1148,7 @@ static void dp83640_remove(struct phy_device *phydev)
|
|||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
|
|
||||||
while ((skb = skb_dequeue(&dp83640->tx_queue)) != NULL)
|
while ((skb = skb_dequeue(&dp83640->tx_queue)) != NULL)
|
||||||
skb_complete_tx_timestamp(skb, NULL);
|
kfree_skb(skb);
|
||||||
|
|
||||||
clock = dp83640_clock_get(dp83640->clock);
|
clock = dp83640_clock_get(dp83640->clock);
|
||||||
|
|
||||||
@ -1405,7 +1405,7 @@ static void dp83640_txtstamp(struct phy_device *phydev,
|
|||||||
|
|
||||||
case HWTSTAMP_TX_ONESTEP_SYNC:
|
case HWTSTAMP_TX_ONESTEP_SYNC:
|
||||||
if (is_sync(skb, type)) {
|
if (is_sync(skb, type)) {
|
||||||
skb_complete_tx_timestamp(skb, NULL);
|
kfree_skb(skb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
@ -1416,7 +1416,7 @@ static void dp83640_txtstamp(struct phy_device *phydev,
|
|||||||
|
|
||||||
case HWTSTAMP_TX_OFF:
|
case HWTSTAMP_TX_OFF:
|
||||||
default:
|
default:
|
||||||
skb_complete_tx_timestamp(skb, NULL);
|
kfree_skb(skb);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2690,6 +2690,8 @@ static inline ktime_t net_invalid_timestamp(void)
|
|||||||
return ktime_set(0, 0);
|
return ktime_set(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct sk_buff *skb_clone_sk(struct sk_buff *skb);
|
||||||
|
|
||||||
#ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
|
#ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
|
||||||
|
|
||||||
void skb_clone_tx_timestamp(struct sk_buff *skb);
|
void skb_clone_tx_timestamp(struct sk_buff *skb);
|
||||||
|
@ -1574,7 +1574,12 @@ struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force,
|
|||||||
void sock_wfree(struct sk_buff *skb);
|
void sock_wfree(struct sk_buff *skb);
|
||||||
void skb_orphan_partial(struct sk_buff *skb);
|
void skb_orphan_partial(struct sk_buff *skb);
|
||||||
void sock_rfree(struct sk_buff *skb);
|
void sock_rfree(struct sk_buff *skb);
|
||||||
|
void sock_efree(struct sk_buff *skb);
|
||||||
|
#ifdef CONFIG_INET
|
||||||
void sock_edemux(struct sk_buff *skb);
|
void sock_edemux(struct sk_buff *skb);
|
||||||
|
#else
|
||||||
|
#define sock_edemux(skb) sock_efree(skb)
|
||||||
|
#endif
|
||||||
|
|
||||||
int sock_setsockopt(struct socket *sock, int level, int op,
|
int sock_setsockopt(struct socket *sock, int level, int op,
|
||||||
char __user *optval, unsigned int optlen);
|
char __user *optval, unsigned int optlen);
|
||||||
|
@ -3511,32 +3511,33 @@ struct sk_buff *sock_dequeue_err_skb(struct sock *sk)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sock_dequeue_err_skb);
|
EXPORT_SYMBOL(sock_dequeue_err_skb);
|
||||||
|
|
||||||
void __skb_tstamp_tx(struct sk_buff *orig_skb,
|
struct sk_buff *skb_clone_sk(struct sk_buff *skb)
|
||||||
struct skb_shared_hwtstamps *hwtstamps,
|
|
||||||
struct sock *sk, int tstype)
|
|
||||||
{
|
{
|
||||||
struct sock_exterr_skb *serr;
|
struct sock *sk = skb->sk;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *clone;
|
||||||
int err;
|
|
||||||
|
|
||||||
if (!sk)
|
if (!sk || !atomic_inc_not_zero(&sk->sk_refcnt))
|
||||||
return;
|
return NULL;
|
||||||
|
|
||||||
if (hwtstamps) {
|
clone = skb_clone(skb, GFP_ATOMIC);
|
||||||
*skb_hwtstamps(orig_skb) =
|
if (!clone) {
|
||||||
*hwtstamps;
|
sock_put(sk);
|
||||||
} else {
|
return NULL;
|
||||||
/*
|
|
||||||
* no hardware time stamps available,
|
|
||||||
* so keep the shared tx_flags and only
|
|
||||||
* store software time stamp
|
|
||||||
*/
|
|
||||||
orig_skb->tstamp = ktime_get_real();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
skb = skb_clone(orig_skb, GFP_ATOMIC);
|
clone->sk = sk;
|
||||||
if (!skb)
|
clone->destructor = sock_efree;
|
||||||
return;
|
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(skb_clone_sk);
|
||||||
|
|
||||||
|
static void __skb_complete_tx_timestamp(struct sk_buff *skb,
|
||||||
|
struct sock *sk,
|
||||||
|
int tstype)
|
||||||
|
{
|
||||||
|
struct sock_exterr_skb *serr;
|
||||||
|
int err;
|
||||||
|
|
||||||
serr = SKB_EXT_ERR(skb);
|
serr = SKB_EXT_ERR(skb);
|
||||||
memset(serr, 0, sizeof(*serr));
|
memset(serr, 0, sizeof(*serr));
|
||||||
@ -3554,6 +3555,42 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
|
|||||||
if (err)
|
if (err)
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void skb_complete_tx_timestamp(struct sk_buff *skb,
|
||||||
|
struct skb_shared_hwtstamps *hwtstamps)
|
||||||
|
{
|
||||||
|
struct sock *sk = skb->sk;
|
||||||
|
|
||||||
|
/* take a reference to prevent skb_orphan() from freeing the socket */
|
||||||
|
sock_hold(sk);
|
||||||
|
|
||||||
|
*skb_hwtstamps(skb) = *hwtstamps;
|
||||||
|
__skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND);
|
||||||
|
|
||||||
|
sock_put(sk);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(skb_complete_tx_timestamp);
|
||||||
|
|
||||||
|
void __skb_tstamp_tx(struct sk_buff *orig_skb,
|
||||||
|
struct skb_shared_hwtstamps *hwtstamps,
|
||||||
|
struct sock *sk, int tstype)
|
||||||
|
{
|
||||||
|
struct sk_buff *skb;
|
||||||
|
|
||||||
|
if (!sk)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (hwtstamps)
|
||||||
|
*skb_hwtstamps(orig_skb) = *hwtstamps;
|
||||||
|
else
|
||||||
|
orig_skb->tstamp = ktime_get_real();
|
||||||
|
|
||||||
|
skb = skb_clone(orig_skb, GFP_ATOMIC);
|
||||||
|
if (!skb)
|
||||||
|
return;
|
||||||
|
|
||||||
|
__skb_complete_tx_timestamp(skb, sk, tstype);
|
||||||
|
}
|
||||||
EXPORT_SYMBOL_GPL(__skb_tstamp_tx);
|
EXPORT_SYMBOL_GPL(__skb_tstamp_tx);
|
||||||
|
|
||||||
void skb_tstamp_tx(struct sk_buff *orig_skb,
|
void skb_tstamp_tx(struct sk_buff *orig_skb,
|
||||||
|
@ -1637,18 +1637,24 @@ void sock_rfree(struct sk_buff *skb)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sock_rfree);
|
EXPORT_SYMBOL(sock_rfree);
|
||||||
|
|
||||||
|
void sock_efree(struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
sock_put(skb->sk);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(sock_efree);
|
||||||
|
|
||||||
|
#ifdef CONFIG_INET
|
||||||
void sock_edemux(struct sk_buff *skb)
|
void sock_edemux(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct sock *sk = skb->sk;
|
struct sock *sk = skb->sk;
|
||||||
|
|
||||||
#ifdef CONFIG_INET
|
|
||||||
if (sk->sk_state == TCP_TIME_WAIT)
|
if (sk->sk_state == TCP_TIME_WAIT)
|
||||||
inet_twsk_put(inet_twsk(sk));
|
inet_twsk_put(inet_twsk(sk));
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
sock_put(sk);
|
sock_put(sk);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sock_edemux);
|
EXPORT_SYMBOL(sock_edemux);
|
||||||
|
#endif
|
||||||
|
|
||||||
kuid_t sock_i_uid(struct sock *sk)
|
kuid_t sock_i_uid(struct sock *sk)
|
||||||
{
|
{
|
||||||
|
@ -36,10 +36,9 @@ void skb_clone_tx_timestamp(struct sk_buff *skb)
|
|||||||
{
|
{
|
||||||
struct phy_device *phydev;
|
struct phy_device *phydev;
|
||||||
struct sk_buff *clone;
|
struct sk_buff *clone;
|
||||||
struct sock *sk = skb->sk;
|
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
|
|
||||||
if (!sk)
|
if (!skb->sk)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
type = classify(skb);
|
type = classify(skb);
|
||||||
@ -48,50 +47,14 @@ void skb_clone_tx_timestamp(struct sk_buff *skb)
|
|||||||
|
|
||||||
phydev = skb->dev->phydev;
|
phydev = skb->dev->phydev;
|
||||||
if (likely(phydev->drv->txtstamp)) {
|
if (likely(phydev->drv->txtstamp)) {
|
||||||
if (!atomic_inc_not_zero(&sk->sk_refcnt))
|
clone = skb_clone_sk(skb);
|
||||||
|
if (!clone)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
clone = skb_clone(skb, GFP_ATOMIC);
|
|
||||||
if (!clone) {
|
|
||||||
sock_put(sk);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
clone->sk = sk;
|
|
||||||
phydev->drv->txtstamp(phydev, clone, type);
|
phydev->drv->txtstamp(phydev, clone, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp);
|
EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp);
|
||||||
|
|
||||||
void skb_complete_tx_timestamp(struct sk_buff *skb,
|
|
||||||
struct skb_shared_hwtstamps *hwtstamps)
|
|
||||||
{
|
|
||||||
struct sock *sk = skb->sk;
|
|
||||||
struct sock_exterr_skb *serr;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if (!hwtstamps) {
|
|
||||||
sock_put(sk);
|
|
||||||
kfree_skb(skb);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
*skb_hwtstamps(skb) = *hwtstamps;
|
|
||||||
|
|
||||||
serr = SKB_EXT_ERR(skb);
|
|
||||||
memset(serr, 0, sizeof(*serr));
|
|
||||||
serr->ee.ee_errno = ENOMSG;
|
|
||||||
serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
|
|
||||||
skb->sk = NULL;
|
|
||||||
|
|
||||||
err = sock_queue_err_skb(sk, skb);
|
|
||||||
|
|
||||||
sock_put(sk);
|
|
||||||
if (err)
|
|
||||||
kfree_skb(skb);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(skb_complete_tx_timestamp);
|
|
||||||
|
|
||||||
bool skb_defer_rx_timestamp(struct sk_buff *skb)
|
bool skb_defer_rx_timestamp(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct phy_device *phydev;
|
struct phy_device *phydev;
|
||||||
|
@ -1972,7 +1972,7 @@ void udp_v4_early_demux(struct sk_buff *skb)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
skb->sk = sk;
|
skb->sk = sk;
|
||||||
skb->destructor = sock_edemux;
|
skb->destructor = sock_efree;
|
||||||
dst = sk->sk_rx_dst;
|
dst = sk->sk_rx_dst;
|
||||||
|
|
||||||
if (dst)
|
if (dst)
|
||||||
|
Loading…
Reference in New Issue
Block a user