net: simplify flags for tx timestamping

This patch removes the abstraction introduced by the union skb_shared_tx in
the shared skb data.

The access of the different union elements at several places led to some
confusion about accessing the shared tx_flags e.g. in skb_orphan_try().

    http://marc.info/?l=linux-netdev&m=128084897415886&w=2

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Oliver Hartkopp 2010-08-17 08:59:14 +00:00 committed by David S. Miller
parent 4d5870ec10
commit 2244d07bfa
17 changed files with 68 additions and 87 deletions

View File

@ -172,15 +172,19 @@ struct skb_shared_hwtstamps {
}; };
Time stamps for outgoing packets are to be generated as follows: Time stamps for outgoing packets are to be generated as follows:
- In hard_start_xmit(), check if skb_tx(skb)->hardware is set no-zero. - In hard_start_xmit(), check if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
If yes, then the driver is expected to do hardware time stamping. is set no-zero. If yes, then the driver is expected to do hardware time
stamping.
- If this is possible for the skb and requested, then declare - If this is possible for the skb and requested, then declare
that the driver is doing the time stamping by setting the field that the driver is doing the time stamping by setting the flag
skb_tx(skb)->in_progress non-zero. You might want to keep a pointer SKBTX_IN_PROGRESS in skb_shinfo(skb)->tx_flags , e.g. with
to the associated skb for the next step and not free the skb. A driver
not supporting hardware time stamping doesn't do that. A driver must skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
never touch sk_buff::tstamp! It is used to store software generated
time stamps by the network subsystem. You might want to keep a pointer to the associated skb for the next step
and not free the skb. A driver not supporting hardware time stamping doesn't
do that. A driver must never touch sk_buff::tstamp! It is used to store
software generated time stamps by the network subsystem.
- As soon as the driver has sent the packet and/or obtained a - As soon as the driver has sent the packet and/or obtained a
hardware time stamp for it, it passes the time stamp back by hardware time stamp for it, it passes the time stamp back by
calling skb_hwtstamp_tx() with the original skb, the raw calling skb_hwtstamp_tx() with the original skb, the raw
@ -191,6 +195,6 @@ Time stamps for outgoing packets are to be generated as follows:
this would occur at a later time in the processing pipeline than other this would occur at a later time in the processing pipeline than other
software time stamping and therefore could lead to unexpected deltas software time stamping and therefore could lead to unexpected deltas
between time stamps. between time stamps.
- If the driver did not call set skb_tx(skb)->in_progress, then - If the driver did not set the SKBTX_IN_PROGRESS flag (see above), then
dev_hard_start_xmit() checks whether software time stamping dev_hard_start_xmit() checks whether software time stamping
is wanted as fallback and potentially generates the time stamp. is wanted as fallback and potentially generates the time stamp.

View File

@ -803,15 +803,14 @@ static void bfin_dump_hwtamp(char *s, ktime_t *hw, ktime_t *ts, struct timecompa
static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
{ {
struct bfin_mac_local *lp = netdev_priv(netdev); struct bfin_mac_local *lp = netdev_priv(netdev);
union skb_shared_tx *shtx = skb_tx(skb);
if (shtx->hardware) { if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
int timeout_cnt = MAX_TIMEOUT_CNT; int timeout_cnt = MAX_TIMEOUT_CNT;
/* When doing time stamping, keep the connection to the socket /* When doing time stamping, keep the connection to the socket
* a while longer * a while longer
*/ */
shtx->in_progress = 1; skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
/* /*
* The timestamping is done at the EMAC module's MII/RMII interface * The timestamping is done at the EMAC module's MII/RMII interface
@ -991,7 +990,6 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
struct bfin_mac_local *lp = netdev_priv(dev); struct bfin_mac_local *lp = netdev_priv(dev);
u16 *data; u16 *data;
u32 data_align = (unsigned long)(skb->data) & 0x3; u32 data_align = (unsigned long)(skb->data) & 0x3;
union skb_shared_tx *shtx = skb_tx(skb);
current_tx_ptr->skb = skb; current_tx_ptr->skb = skb;
@ -1005,7 +1003,7 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
* of this field are the length of the packet payload in bytes and the higher * of this field are the length of the packet payload in bytes and the higher
* 4 bits are the timestamping enable field. * 4 bits are the timestamping enable field.
*/ */
if (shtx->hardware) if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
*data |= 0x1000; *data |= 0x1000;
current_tx_ptr->desc_a.start_addr = (u32)data; current_tx_ptr->desc_a.start_addr = (u32)data;
@ -1015,7 +1013,7 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
} else { } else {
*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len); *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
/* enable timestamping for the sent packet */ /* enable timestamping for the sent packet */
if (shtx->hardware) if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
*((u16 *)(current_tx_ptr->packet)) |= 0x1000; *((u16 *)(current_tx_ptr->packet)) |= 0x1000;
memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data, memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
skb->len); skb->len);

View File

@ -2048,7 +2048,6 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
u32 bufaddr; u32 bufaddr;
unsigned long flags; unsigned long flags;
unsigned int nr_frags, nr_txbds, length; unsigned int nr_frags, nr_txbds, length;
union skb_shared_tx *shtx;
/* /*
* TOE=1 frames larger than 2500 bytes may see excess delays * TOE=1 frames larger than 2500 bytes may see excess delays
@ -2069,10 +2068,10 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
txq = netdev_get_tx_queue(dev, rq); txq = netdev_get_tx_queue(dev, rq);
base = tx_queue->tx_bd_base; base = tx_queue->tx_bd_base;
regs = tx_queue->grp->regs; regs = tx_queue->grp->regs;
shtx = skb_tx(skb);
/* check if time stamp should be generated */ /* check if time stamp should be generated */
if (unlikely(shtx->hardware && priv->hwts_tx_en)) if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
priv->hwts_tx_en))
do_tstamp = 1; do_tstamp = 1;
/* make space for additional header when fcb is needed */ /* make space for additional header when fcb is needed */
@ -2174,7 +2173,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Setup tx hardware time stamping if requested */ /* Setup tx hardware time stamping if requested */
if (unlikely(do_tstamp)) { if (unlikely(do_tstamp)) {
shtx->in_progress = 1; skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
if (fcb == NULL) if (fcb == NULL)
fcb = gfar_add_fcb(skb); fcb = gfar_add_fcb(skb);
fcb->ptp = 1; fcb->ptp = 1;
@ -2446,7 +2445,6 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
int howmany = 0; int howmany = 0;
u32 lstatus; u32 lstatus;
size_t buflen; size_t buflen;
union skb_shared_tx *shtx;
rx_queue = priv->rx_queue[tx_queue->qindex]; rx_queue = priv->rx_queue[tx_queue->qindex];
bdp = tx_queue->dirty_tx; bdp = tx_queue->dirty_tx;
@ -2461,8 +2459,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
* When time stamping, one additional TxBD must be freed. * When time stamping, one additional TxBD must be freed.
* Also, we need to dma_unmap_single() the TxPAL. * Also, we need to dma_unmap_single() the TxPAL.
*/ */
shtx = skb_tx(skb); if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))
if (unlikely(shtx->in_progress))
nr_txbds = frags + 2; nr_txbds = frags + 2;
else else
nr_txbds = frags + 1; nr_txbds = frags + 1;
@ -2476,7 +2473,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
(lstatus & BD_LENGTH_MASK)) (lstatus & BD_LENGTH_MASK))
break; break;
if (unlikely(shtx->in_progress)) { if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
next = next_txbd(bdp, base, tx_ring_size); next = next_txbd(bdp, base, tx_ring_size);
buflen = next->length + GMAC_FCB_LEN; buflen = next->length + GMAC_FCB_LEN;
} else } else
@ -2485,7 +2482,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr, dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr,
buflen, DMA_TO_DEVICE); buflen, DMA_TO_DEVICE);
if (unlikely(shtx->in_progress)) { if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
struct skb_shared_hwtstamps shhwtstamps; struct skb_shared_hwtstamps shhwtstamps;
u64 *ns = (u64*) (((u32)skb->data + 0x10) & ~0x7); u64 *ns = (u64*) (((u32)skb->data + 0x10) & ~0x7);
memset(&shhwtstamps, 0, sizeof(shhwtstamps)); memset(&shhwtstamps, 0, sizeof(shhwtstamps));

View File

@ -143,7 +143,7 @@ struct igb_buffer {
u16 next_to_watch; u16 next_to_watch;
unsigned int bytecount; unsigned int bytecount;
u16 gso_segs; u16 gso_segs;
union skb_shared_tx shtx; u8 tx_flags;
u8 mapped_as_page; u8 mapped_as_page;
}; };
/* RX */ /* RX */

View File

@ -3954,7 +3954,7 @@ static inline int igb_tx_map_adv(struct igb_ring *tx_ring, struct sk_buff *skb,
} }
tx_ring->buffer_info[i].skb = skb; tx_ring->buffer_info[i].skb = skb;
tx_ring->buffer_info[i].shtx = skb_shinfo(skb)->tx_flags; tx_ring->buffer_info[i].tx_flags = skb_shinfo(skb)->tx_flags;
/* multiply data chunks by size of headers */ /* multiply data chunks by size of headers */
tx_ring->buffer_info[i].bytecount = ((gso_segs - 1) * hlen) + skb->len; tx_ring->buffer_info[i].bytecount = ((gso_segs - 1) * hlen) + skb->len;
tx_ring->buffer_info[i].gso_segs = gso_segs; tx_ring->buffer_info[i].gso_segs = gso_segs;
@ -4088,7 +4088,6 @@ netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
u32 tx_flags = 0; u32 tx_flags = 0;
u16 first; u16 first;
u8 hdr_len = 0; u8 hdr_len = 0;
union skb_shared_tx *shtx = skb_tx(skb);
/* need: 1 descriptor per page, /* need: 1 descriptor per page,
* + 2 desc gap to keep tail from touching head, * + 2 desc gap to keep tail from touching head,
@ -4100,8 +4099,8 @@ netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
} }
if (unlikely(shtx->hardware)) { if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
shtx->in_progress = 1; skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
tx_flags |= IGB_TX_FLAGS_TSTAMP; tx_flags |= IGB_TX_FLAGS_TSTAMP;
} }
@ -5319,7 +5318,7 @@ static void igb_tx_hwtstamp(struct igb_q_vector *q_vector, struct igb_buffer *bu
u64 regval; u64 regval;
/* if skb does not support hw timestamp or TX stamp not valid exit */ /* if skb does not support hw timestamp or TX stamp not valid exit */
if (likely(!buffer_info->shtx.hardware) || if (likely(!(buffer_info->tx_flags & SKBTX_HW_TSTAMP)) ||
!(rd32(E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID)) !(rd32(E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID))
return; return;
@ -5500,7 +5499,7 @@ static void igb_rx_hwtstamp(struct igb_q_vector *q_vector, u32 staterr,
* values must belong to this one here and therefore we don't need to * values must belong to this one here and therefore we don't need to
* compare any of the additional attributes stored for it. * compare any of the additional attributes stored for it.
* *
* If nothing went wrong, then it should have a skb_shared_tx that we * If nothing went wrong, then it should have a shared tx_flags that we
* can turn into a skb_shared_hwtstamps. * can turn into a skb_shared_hwtstamps.
*/ */
if (staterr & E1000_RXDADV_STAT_TSIP) { if (staterr & E1000_RXDADV_STAT_TSIP) {

View File

@ -163,26 +163,19 @@ struct skb_shared_hwtstamps {
ktime_t syststamp; ktime_t syststamp;
}; };
/** /* Definitions for tx_flags in struct skb_shared_info */
* struct skb_shared_tx - instructions for time stamping of outgoing packets enum {
* @hardware: generate hardware time stamp /* generate hardware time stamp */
* @software: generate software time stamp SKBTX_HW_TSTAMP = 1 << 0,
* @in_progress: device driver is going to provide
* hardware time stamp /* generate software time stamp */
* @prevent_sk_orphan: make sk reference available on driver level SKBTX_SW_TSTAMP = 1 << 1,
* @flags: all shared_tx flags
* /* device driver is going to provide hardware time stamp */
* These flags are attached to packets as part of the SKBTX_IN_PROGRESS = 1 << 2,
* &skb_shared_info. Use skb_tx() to get a pointer.
*/ /* ensure the originating sk reference is available on driver level */
union skb_shared_tx { SKBTX_DRV_NEEDS_SK_REF = 1 << 3,
struct {
__u8 hardware:1,
software:1,
in_progress:1,
prevent_sk_orphan:1;
};
__u8 flags;
}; };
/* This data is invariant across clones and lives at /* This data is invariant across clones and lives at
@ -195,7 +188,7 @@ struct skb_shared_info {
unsigned short gso_segs; unsigned short gso_segs;
unsigned short gso_type; unsigned short gso_type;
__be32 ip6_frag_id; __be32 ip6_frag_id;
union skb_shared_tx tx_flags; __u8 tx_flags;
struct sk_buff *frag_list; struct sk_buff *frag_list;
struct skb_shared_hwtstamps hwtstamps; struct skb_shared_hwtstamps hwtstamps;
@ -587,11 +580,6 @@ static inline struct skb_shared_hwtstamps *skb_hwtstamps(struct sk_buff *skb)
return &skb_shinfo(skb)->hwtstamps; return &skb_shinfo(skb)->hwtstamps;
} }
static inline union skb_shared_tx *skb_tx(struct sk_buff *skb)
{
return &skb_shinfo(skb)->tx_flags;
}
/** /**
* skb_queue_empty - check if a queue is empty * skb_queue_empty - check if a queue is empty
* @list: queue head * @list: queue head
@ -1996,8 +1984,8 @@ extern void skb_tstamp_tx(struct sk_buff *orig_skb,
static inline void sw_tx_timestamp(struct sk_buff *skb) static inline void sw_tx_timestamp(struct sk_buff *skb)
{ {
union skb_shared_tx *shtx = skb_tx(skb); if (skb_shinfo(skb)->tx_flags & SKBTX_SW_TSTAMP &&
if (shtx->software && !shtx->in_progress) !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))
skb_tstamp_tx(skb, NULL); skb_tstamp_tx(skb, NULL);
} }

View File

@ -53,7 +53,7 @@ struct ipcm_cookie {
__be32 addr; __be32 addr;
int oif; int oif;
struct ip_options *opt; struct ip_options *opt;
union skb_shared_tx shtx; __u8 tx_flags;
}; };
#define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb)) #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))

View File

@ -1669,17 +1669,13 @@ static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
/** /**
* sock_tx_timestamp - checks whether the outgoing packet is to be time stamped * sock_tx_timestamp - checks whether the outgoing packet is to be time stamped
* @msg: outgoing packet
* @sk: socket sending this packet * @sk: socket sending this packet
* @shtx: filled with instructions for time stamping * @tx_flags: filled with instructions for time stamping
* *
* Currently only depends on SOCK_TIMESTAMPING* flags. Returns error code if * Currently only depends on SOCK_TIMESTAMPING* flags. Returns error code if
* parameters are invalid. * parameters are invalid.
*/ */
extern int sock_tx_timestamp(struct msghdr *msg, extern int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags);
struct sock *sk,
union skb_shared_tx *shtx);
/** /**
* sk_eat_skb - Release a skb if it is no longer needed * sk_eat_skb - Release a skb if it is no longer needed

View File

@ -647,12 +647,12 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
if (err < 0) if (err < 0)
goto free_skb; goto free_skb;
err = sock_tx_timestamp(msg, sk, skb_tx(skb)); err = sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags);
if (err < 0) if (err < 0)
goto free_skb; goto free_skb;
/* to be able to check the received tx sock reference in raw_rcv() */ /* to be able to check the received tx sock reference in raw_rcv() */
skb_tx(skb)->prevent_sk_orphan = 1; skb_shinfo(skb)->tx_flags |= SKBTX_DRV_NEEDS_SK_REF;
skb->dev = dev; skb->dev = dev;
skb->sk = sk; skb->sk = sk;

View File

@ -1902,14 +1902,14 @@ static int dev_gso_segment(struct sk_buff *skb)
/* /*
* Try to orphan skb early, right before transmission by the device. * Try to orphan skb early, right before transmission by the device.
* We cannot orphan skb if tx timestamp is requested, since * We cannot orphan skb if tx timestamp is requested or the sk-reference
* drivers need to call skb_tstamp_tx() to send the timestamp. * is needed on driver level for other reasons, e.g. see net/can/raw.c
*/ */
static inline void skb_orphan_try(struct sk_buff *skb) static inline void skb_orphan_try(struct sk_buff *skb)
{ {
struct sock *sk = skb->sk; struct sock *sk = skb->sk;
if (sk && !skb_tx(skb)->flags) { if (sk && !skb_shinfo(skb)->tx_flags) {
/* skb_tx_hash() wont be able to get sk. /* skb_tx_hash() wont be able to get sk.
* We copy sk_hash into skb->rxhash * We copy sk_hash into skb->rxhash
*/ */

View File

@ -3016,7 +3016,7 @@ void skb_tstamp_tx(struct sk_buff *orig_skb,
} else { } else {
/* /*
* no hardware time stamps available, * no hardware time stamps available,
* so keep the skb_shared_tx and only * so keep the shared tx_flags and only
* store software time stamp * store software time stamp
*/ */
skb->tstamp = ktime_get_real(); skb->tstamp = ktime_get_real();

View File

@ -379,7 +379,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
inet->tos = ip_hdr(skb)->tos; inet->tos = ip_hdr(skb)->tos;
daddr = ipc.addr = rt->rt_src; daddr = ipc.addr = rt->rt_src;
ipc.opt = NULL; ipc.opt = NULL;
ipc.shtx.flags = 0; ipc.tx_flags = 0;
if (icmp_param->replyopts.optlen) { if (icmp_param->replyopts.optlen) {
ipc.opt = &icmp_param->replyopts; ipc.opt = &icmp_param->replyopts;
if (ipc.opt->srr) if (ipc.opt->srr)
@ -538,7 +538,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
inet_sk(sk)->tos = tos; inet_sk(sk)->tos = tos;
ipc.addr = iph->saddr; ipc.addr = iph->saddr;
ipc.opt = &icmp_param.replyopts; ipc.opt = &icmp_param.replyopts;
ipc.shtx.flags = 0; ipc.tx_flags = 0;
{ {
struct flowi fl = { struct flowi fl = {

View File

@ -953,7 +953,7 @@ alloc_new_skb:
else else
/* only the initial fragment is /* only the initial fragment is
time stamped */ time stamped */
ipc->shtx.flags = 0; ipc->tx_flags = 0;
} }
if (skb == NULL) if (skb == NULL)
goto error; goto error;
@ -964,7 +964,7 @@ alloc_new_skb:
skb->ip_summed = csummode; skb->ip_summed = csummode;
skb->csum = 0; skb->csum = 0;
skb_reserve(skb, hh_len); skb_reserve(skb, hh_len);
*skb_tx(skb) = ipc->shtx; skb_shinfo(skb)->tx_flags = ipc->tx_flags;
/* /*
* Find where to start putting bytes. * Find where to start putting bytes.
@ -1384,7 +1384,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
daddr = ipc.addr = rt->rt_src; daddr = ipc.addr = rt->rt_src;
ipc.opt = NULL; ipc.opt = NULL;
ipc.shtx.flags = 0; ipc.tx_flags = 0;
if (replyopts.opt.optlen) { if (replyopts.opt.optlen) {
ipc.opt = &replyopts.opt; ipc.opt = &replyopts.opt;

View File

@ -505,7 +505,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
ipc.addr = inet->inet_saddr; ipc.addr = inet->inet_saddr;
ipc.opt = NULL; ipc.opt = NULL;
ipc.shtx.flags = 0; ipc.tx_flags = 0;
ipc.oif = sk->sk_bound_dev_if; ipc.oif = sk->sk_bound_dev_if;
if (msg->msg_controllen) { if (msg->msg_controllen) {

View File

@ -797,7 +797,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
return -EOPNOTSUPP; return -EOPNOTSUPP;
ipc.opt = NULL; ipc.opt = NULL;
ipc.shtx.flags = 0; ipc.tx_flags = 0;
if (up->pending) { if (up->pending) {
/* /*
@ -845,7 +845,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
ipc.addr = inet->inet_saddr; ipc.addr = inet->inet_saddr;
ipc.oif = sk->sk_bound_dev_if; ipc.oif = sk->sk_bound_dev_if;
err = sock_tx_timestamp(msg, sk, &ipc.shtx); err = sock_tx_timestamp(sk, &ipc.tx_flags);
if (err) if (err)
return err; return err;
if (msg->msg_controllen) { if (msg->msg_controllen) {

View File

@ -488,7 +488,7 @@ retry:
skb->dev = dev; skb->dev = dev;
skb->priority = sk->sk_priority; skb->priority = sk->sk_priority;
skb->mark = sk->sk_mark; skb->mark = sk->sk_mark;
err = sock_tx_timestamp(msg, sk, skb_tx(skb)); err = sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags);
if (err < 0) if (err < 0)
goto out_unlock; goto out_unlock;
@ -1209,7 +1209,7 @@ static int packet_snd(struct socket *sock,
err = skb_copy_datagram_from_iovec(skb, offset, msg->msg_iov, 0, len); err = skb_copy_datagram_from_iovec(skb, offset, msg->msg_iov, 0, len);
if (err) if (err)
goto out_free; goto out_free;
err = sock_tx_timestamp(msg, sk, skb_tx(skb)); err = sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags);
if (err < 0) if (err < 0)
goto out_free; goto out_free;

View File

@ -535,14 +535,13 @@ void sock_release(struct socket *sock)
} }
EXPORT_SYMBOL(sock_release); EXPORT_SYMBOL(sock_release);
int sock_tx_timestamp(struct msghdr *msg, struct sock *sk, int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
union skb_shared_tx *shtx)
{ {
shtx->flags = 0; *tx_flags = 0;
if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE)) if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE))
shtx->hardware = 1; *tx_flags |= SKBTX_HW_TSTAMP;
if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE)) if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
shtx->software = 1; *tx_flags |= SKBTX_SW_TSTAMP;
return 0; return 0;
} }
EXPORT_SYMBOL(sock_tx_timestamp); EXPORT_SYMBOL(sock_tx_timestamp);