]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: macb: match skb_reserve(skb, NET_IP_ALIGN) with HW alignment
authorThéo Lebrun <theo.lebrun@bootlin.com>
Thu, 23 Oct 2025 16:22:52 +0000 (18:22 +0200)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 28 Oct 2025 14:17:54 +0000 (15:17 +0100)
If HW is RSC capable, it cannot add dummy bytes at the start of IP
packets. Alignment (ie number of dummy bytes) is configured using the
RBOF field inside the NCFGR register.

On the software side, the skb_reserve(skb, NET_IP_ALIGN) call must only
be done if those dummy bytes are added by the hardware; notice the
skb_reserve() is done AFTER writing the address to the device.

We cannot do the skb_reserve() call BEFORE writing the address because
the address field ignores the low 2/3 bits. Conclusion: in some cases,
we risk not being able to respect the NET_IP_ALIGN value (which is
picked based on unaligned CPU access performance).

Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20251023-macb-eyeq5-v3-2-af509422c204@bootlin.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/cadence/macb.h
drivers/net/ethernet/cadence/macb_main.c

index 5b7d4cdb204d8362bfa81dcc58965edbbf4dd1f8..93e8dd092313e81dbee690188ccc88050c41d1ad 100644 (file)
 /* Bitfields in DCFG6. */
 #define GEM_PBUF_LSO_OFFSET                    27
 #define GEM_PBUF_LSO_SIZE                      1
+#define GEM_PBUF_RSC_OFFSET                    26
+#define GEM_PBUF_RSC_SIZE                      1
 #define GEM_PBUF_CUTTHRU_OFFSET                        25
 #define GEM_PBUF_CUTTHRU_SIZE                  1
 #define GEM_DAW64_OFFSET                       23
 #define MACB_CAPS_MACB_IS_GEM                  BIT(20)
 #define MACB_CAPS_DMA_64B                      BIT(21)
 #define MACB_CAPS_DMA_PTP                      BIT(22)
+#define MACB_CAPS_RSC                          BIT(23)
 
 /* LSO settings */
 #define MACB_LSO_UFO_ENABLE                    0x01
index 39673f5c3337feef0ead650317c2c8f8a25d194e..be3d0c2313a16078b36dacb23c3c1e831a9f6c46 100644 (file)
@@ -1300,8 +1300,19 @@ static void gem_rx_refill(struct macb_queue *queue)
                        dma_wmb();
                        macb_set_addr(bp, desc, paddr);
 
-                       /* properly align Ethernet header */
-                       skb_reserve(skb, NET_IP_ALIGN);
+                       /* Properly align Ethernet header.
+                        *
+                        * Hardware can add dummy bytes if asked using the RBOF
+                        * field inside the NCFGR register. That feature isn't
+                        * available if hardware is RSC capable.
+                        *
+                        * We cannot fallback to doing the 2-byte shift before
+                        * DMA mapping because the address field does not allow
+                        * setting the low 2/3 bits.
+                        * It is 3 bits if HW_DMA_CAP_PTP, else 2 bits.
+                        */
+                       if (!(bp->caps & MACB_CAPS_RSC))
+                               skb_reserve(skb, NET_IP_ALIGN);
                } else {
                        desc->ctrl = 0;
                        dma_wmb();
@@ -2773,7 +2784,11 @@ static void macb_init_hw(struct macb *bp)
        macb_set_hwaddr(bp);
 
        config = macb_mdc_clk_div(bp);
-       config |= MACB_BF(RBOF, NET_IP_ALIGN);  /* Make eth data aligned */
+       /* Make eth data aligned.
+        * If RSC capable, that offset is ignored by HW.
+        */
+       if (!(bp->caps & MACB_CAPS_RSC))
+               config |= MACB_BF(RBOF, NET_IP_ALIGN);
        config |= MACB_BIT(DRFCS);              /* Discard Rx FCS */
        if (bp->caps & MACB_CAPS_JUMBO)
                config |= MACB_BIT(JFRAME);     /* Enable jumbo frames */
@@ -4321,6 +4336,8 @@ static void macb_configure_caps(struct macb *bp,
                dcfg = gem_readl(bp, DCFG2);
                if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0)
                        bp->caps |= MACB_CAPS_FIFO_MODE;
+               if (GEM_BFEXT(PBUF_RSC, gem_readl(bp, DCFG6)))
+                       bp->caps |= MACB_CAPS_RSC;
                if (gem_has_ptp(bp)) {
                        if (!GEM_BFEXT(TSU, gem_readl(bp, DCFG5)))
                                dev_err(&bp->pdev->dev,