Re: [REGRESSION] Commit 447cbe95ebb9 causes IOMMU DMA faults on macvlan/vlan with bnxt_en
flat view
From: Eric Dumazet <edumazet@kernel.org>
Date: 2026-10-04 21:11:29
Also in:
regressions, stable
Subsystem:
broadcom bnxt_en 50 gigabit ethernet driver, networking drivers, the rest · Maintainers:
Michael Chan, Pavan Chebbi, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
On 10/4/26 22:52, Eric Dumazet wrote:
quoted hunk ↗ jump to hunk
On 10/4/26 19:29, Stefan Fleischmann wrote:quoted
On Sun, 4 Oct 2026 16:35:32 +0200 Stefan Fleischmann [off-list ref] wrote:quoted
On Sun, 4 Oct 2026 13:46:08 +0200 Eric Dumazet [off-list ref] wrote:quoted
Notice that 0xfc499000 is on an exact 4KB page boundary. This points to a DMA read overrun where the Broadcom DMA engine reads past the end of a buffer mapped in page 0xfc498xxx into the adjacent unmapped page 0xfc499000. Have you tried a recent net kernel ?Hi Eric, that might be a bit tricky. We use ZFS on this server and the version we have installed only supports up to kernel 7.2.Scratch that, I noticed that this even happens with none of the LXC containers running. So I tested with the main branch from https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git (commit 6dc989ea46b9) Same issue.Okay, this must be a bnxt issue, that has been hidden years because of some skb->data headroom/offset. LL_RESERVED_SPACE() has been increased from 48 to 64. So perhaps small packets are now crossing a page boundary (which should be fine) I see one bug in the skb_pad() vicinity. Could you try:diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ ethernet/broadcom/bnxt/bnxt.c index d7728d0c5b6e63ee72de9dea54426bb4c8b7a9fc..f9feeb4471a8cf310788ef8d00b68a1508a7e78e 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c@@ -678,6 +678,7 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev) /* SKB already freed. */ goto tx_kick_pending; length = BNXT_MIN_PKT_SIZE; + len += pad; } mapping = dma_map_single(&pdev->dev, skb->data, len, DMA_TO_DEVICE);
A more polished patch would be this one. bnxt_start_xmit() needs an audit I think :/
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index d7728d0c5b6e63ee72de9dea54426bb4c8b7a9fc..48e544544754b04cff891bda5bc86cc370e0aa0b 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c@@ -486,7 +486,7 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev) struct netdev_queue *txq; int i; dma_addr_t mapping; - unsigned int length, pad = 0; + unsigned int length; u32 len, free_size, vlan_tag_flags, cfa_action, flags; struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; struct pci_dev *pdev = bp->pdev;
@@ -672,14 +672,12 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev) } normal_tx: - if (length < BNXT_MIN_PKT_SIZE) { - pad = BNXT_MIN_PKT_SIZE - length; - if (skb_pad(skb, pad)) - /* SKB already freed. */ - goto tx_kick_pending; - length = BNXT_MIN_PKT_SIZE; + if (skb_padto(skb, BNXT_MIN_PKT_SIZE)) { + /* SKB already freed. */ + goto tx_kick_pending; } - + length = skb->len; + len = skb_headlen(skb); mapping = dma_map_single(&pdev->dev, skb->data, len, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(&pdev->dev, mapping)))
@@ -759,10 +757,7 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev) txbd->tx_bd_len_flags_type = cpu_to_le32(flags); } - flags &= ~TX_BD_LEN; - txbd->tx_bd_len_flags_type = - cpu_to_le32(((len + pad) << TX_BD_LEN_SHIFT) | flags | - TX_BD_FLAGS_PACKET_END); + txbd->tx_bd_len_flags_type |= cpu_to_le32(TX_BD_FLAGS_PACKET_END); netdev_tx_sent_queue(txq, skb->len);