[PATCH net 2/3] igc: prepare TSO and checksum offloads before TX timestamps
From: Paul Moses
Date: Mon Oct 26 2026 - 05:16:46 EST
igc_request_tx_tstamp() takes an extra skb reference before transmit
preparation. For GSO packets, igc_tso() calls skb_cow_head(), which can
reach pskb_expand_head() with a shared skb when the header is cloned.
Commit c7d8bc3dd511 ("net: skbuff: don't BUG() on bad arguments to
pskb_expand_head()") replaced the BUG_ON() with -EINVAL, causing TSO
preparation to fail and the packet to be dropped.
For non-GSO packets with CHECKSUM_PARTIAL, igc_tx_csum() falls back to
skb_checksum_help() for unsupported checksum offsets. This can also
reach pskb_expand_head() through skb_ensure_writable(). igc_tx_csum()
ignores the error, allowing transmission to continue without completing
the checksum.
Move TSO and checksum preparation before TX timestamp reservation so
the extra skb reference cannot interfere with either operation.
Fixes: 2c344ae24501 ("igc: Add support for TX timestamping")
Fixes: f38b782dccab ("igc: Add support for TSO")
Signed-off-by: Paul Moses <p@xxxxxxx>
---
drivers/net/ethernet/intel/igc/igc_main.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index f1bf4e462a51..cd4c9815fca7 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -1678,6 +1678,12 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb,
goto out_drop;
}
+ tso = igc_tso(tx_ring, first, launch_time, first_flag, &hdr_len);
+ if (tso < 0)
+ goto out_drop;
+ else if (!tso)
+ igc_tx_csum(tx_ring, first, launch_time, first_flag);
+
if (unlikely(test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags) &&
skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
unsigned long flags;
@@ -1697,12 +1703,6 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb,
spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
}
- tso = igc_tso(tx_ring, first, launch_time, first_flag, &hdr_len);
- if (tso < 0)
- goto out_drop;
- else if (!tso)
- igc_tx_csum(tx_ring, first, launch_time, first_flag);
-
igc_tx_map(tx_ring, first, hdr_len);
return NETDEV_TX_OK;