Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2c048e64 authored by David S. Miller's avatar David S. Miller
Browse files

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
====================
parents d546c621 82eabd9e
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -1148,7 +1148,7 @@ static void dp83640_remove(struct phy_device *phydev)
		kfree_skb(skb);

	while ((skb = skb_dequeue(&dp83640->tx_queue)) != NULL)
		skb_complete_tx_timestamp(skb, NULL);
		kfree_skb(skb);

	clock = dp83640_clock_get(dp83640->clock);

@@ -1405,7 +1405,7 @@ static void dp83640_txtstamp(struct phy_device *phydev,

	case HWTSTAMP_TX_ONESTEP_SYNC:
		if (is_sync(skb, type)) {
			skb_complete_tx_timestamp(skb, NULL);
			kfree_skb(skb);
			return;
		}
		/* fall through */
@@ -1416,7 +1416,7 @@ static void dp83640_txtstamp(struct phy_device *phydev,

	case HWTSTAMP_TX_OFF:
	default:
		skb_complete_tx_timestamp(skb, NULL);
		kfree_skb(skb);
		break;
	}
}
+2 −0
Original line number Diff line number Diff line
@@ -2690,6 +2690,8 @@ static inline ktime_t net_invalid_timestamp(void)
	return ktime_set(0, 0);
}

struct sk_buff *skb_clone_sk(struct sk_buff *skb);

#ifdef CONFIG_NETWORK_PHY_TIMESTAMPING

void skb_clone_tx_timestamp(struct sk_buff *skb);
+5 −0
Original line number Diff line number Diff line
@@ -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 skb_orphan_partial(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);
#else
#define sock_edemux(skb) sock_efree(skb)
#endif

int sock_setsockopt(struct socket *sock, int level, int op,
		    char __user *optval, unsigned int optlen);
+58 −21
Original line number Diff line number Diff line
@@ -3511,32 +3511,33 @@ struct sk_buff *sock_dequeue_err_skb(struct sock *sk)
}
EXPORT_SYMBOL(sock_dequeue_err_skb);

void __skb_tstamp_tx(struct sk_buff *orig_skb,
		     struct skb_shared_hwtstamps *hwtstamps,
		     struct sock *sk, int tstype)
struct sk_buff *skb_clone_sk(struct sk_buff *skb)
{
	struct sock_exterr_skb *serr;
	struct sk_buff *skb;
	int err;
	struct sock *sk = skb->sk;
	struct sk_buff *clone;

	if (!sk)
		return;
	if (!sk || !atomic_inc_not_zero(&sk->sk_refcnt))
		return NULL;

	if (hwtstamps) {
		*skb_hwtstamps(orig_skb) =
			*hwtstamps;
	} else {
		/*
		 * no hardware time stamps available,
		 * so keep the shared tx_flags and only
		 * store software time stamp
		 */
		orig_skb->tstamp = ktime_get_real();
	clone = skb_clone(skb, GFP_ATOMIC);
	if (!clone) {
		sock_put(sk);
		return NULL;
	}

	skb = skb_clone(orig_skb, GFP_ATOMIC);
	if (!skb)
		return;
	clone->sk = sk;
	clone->destructor = sock_efree;

	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);
	memset(serr, 0, sizeof(*serr));
@@ -3554,6 +3555,42 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
	if (err)
		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);

void skb_tstamp_tx(struct sk_buff *orig_skb,
+8 −2
Original line number Diff line number Diff line
@@ -1637,18 +1637,24 @@ void sock_rfree(struct sk_buff *skb)
}
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)
{
	struct sock *sk = skb->sk;

#ifdef CONFIG_INET
	if (sk->sk_state == TCP_TIME_WAIT)
		inet_twsk_put(inet_twsk(sk));
	else
#endif
		sock_put(sk);
}
EXPORT_SYMBOL(sock_edemux);
#endif

kuid_t sock_i_uid(struct sock *sk)
{
Loading