Thread (16 messages) 16 messages, 7 authors, 4d ago

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);


Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help