Looks like I got it wrong in the first place. priv->tx_buff is not for the device, so there's no need to move it. The race has been fixed by commit c278c253f3d9, I forgot to check it out. That's my fault. I do find another problem. We need to use a barrier to make sure skb_tx_timestamp() is called before setting the FOR_EMAC flag. According to the comment(include/linux/skbuff.h): >/** > * skb_tx_timestamp() - Driver hook for transmit timestamping > * > * Ethernet MAC Drivers should call this function in their hard_xmit() > * function immediately before giving the sk_buff to the MAC hardware. > * > * Specifically, one should make absolutely sure that this function is > * called before TX completion of this packet can trigger. Otherwise > * the packet could potentially already be freed. > * > * @skb: A socket buffer. > */ --- diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c index a3a9392..c2447b0 100644 --- a/drivers/net/ethernet/arc/emac_main.c +++ b/drivers/net/ethernet/arc/emac_main.c @@ -686,6 +686,9 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev) skb_tx_timestamp(skb); + /* Make sure timestamp is set */ + smp_wmb(); + *info = cpu_to_le32(FOR_EMAC | FIRST_OR_LAST_MASK | len); /* Make sure info word is set */