Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: ionic: map SKB after pseudo-header checksum prep

The TSO path called ionic_tx_map_skb() before preparing the TCP pseudo
checksum (ionic_tx_tcp_[inner_]pseudo_csum()), which may perform
skb_cow_head() and might modifies bytes in the linear header area.

Mapping first and then mutating the header risks:
- Using a stale DMA address if skb_cow_head() relocates the head, and/or
- Device reading stale header bytes on weakly-ordered systems
(CPU writes after mapping are not guaranteed visible without an
explicit dma_sync_single_for_device()).

Reorder the TX path to perform all header mutations (including
skb_cow_head()) *before* DMA mapping. Mapping is now done only after the
skb layout and header contents are final. This removes the need for any
post-mapping dma_sync and prevents on-wire corruption observed under
VLAN+TSO load after repeated runs.

This change is purely an ordering fix; no functional behavior change
otherwise.

Fixes: 0f3154e6bcb3 ("ionic: Add Tx and Rx handling")
Signed-off-by: Mohammad Heib <mheib@redhat.com>
Reviewed-by: Brett Creeley <brett.creeley@amd.com>
Link: https://patch.msgid.link/20251031155203.203031-2-mheib@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Mohammad Heib and committed by
Jakub Kicinski
de0337d6 d261f5b0

+13 -17
+13 -17
drivers/net/ethernet/pensando/ionic/ionic_txrx.c
··· 1448 1448 bool encap; 1449 1449 int err; 1450 1450 1451 - desc_info = &q->tx_info[q->head_idx]; 1452 - 1453 - if (unlikely(ionic_tx_map_skb(q, skb, desc_info))) 1454 - return -EIO; 1455 - 1456 - len = skb->len; 1457 - mss = skb_shinfo(skb)->gso_size; 1458 - outer_csum = (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE | 1459 - SKB_GSO_GRE_CSUM | 1460 - SKB_GSO_IPXIP4 | 1461 - SKB_GSO_IPXIP6 | 1462 - SKB_GSO_UDP_TUNNEL | 1463 - SKB_GSO_UDP_TUNNEL_CSUM)); 1464 1451 has_vlan = !!skb_vlan_tag_present(skb); 1465 1452 vlan_tci = skb_vlan_tag_get(skb); 1466 1453 encap = skb->encapsulation; ··· 1461 1474 err = ionic_tx_tcp_inner_pseudo_csum(skb); 1462 1475 else 1463 1476 err = ionic_tx_tcp_pseudo_csum(skb); 1464 - if (unlikely(err)) { 1465 - /* clean up mapping from ionic_tx_map_skb */ 1466 - ionic_tx_desc_unmap_bufs(q, desc_info); 1477 + if (unlikely(err)) 1467 1478 return err; 1468 - } 1469 1479 1480 + desc_info = &q->tx_info[q->head_idx]; 1481 + if (unlikely(ionic_tx_map_skb(q, skb, desc_info))) 1482 + return -EIO; 1483 + 1484 + len = skb->len; 1485 + mss = skb_shinfo(skb)->gso_size; 1486 + outer_csum = (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE | 1487 + SKB_GSO_GRE_CSUM | 1488 + SKB_GSO_IPXIP4 | 1489 + SKB_GSO_IPXIP6 | 1490 + SKB_GSO_UDP_TUNNEL | 1491 + SKB_GSO_UDP_TUNNEL_CSUM)); 1470 1492 if (encap) 1471 1493 hdrlen = skb_inner_tcp_all_headers(skb); 1472 1494 else