summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/cadence/macb_main.c
diff options
context:
space:
mode:
authorThéo Lebrun <theo.lebrun@bootlin.com>2025-10-23 18:22:52 +0200
committerPaolo Abeni <pabeni@redhat.com>2025-10-28 15:17:54 +0100
commitae7a9585ea6974bd7a772fee96bb8514e250dbd6 (patch)
tree1db8909e3334e91eb1155610b97f3d157ac38dcd /drivers/net/ethernet/cadence/macb_main.c
parentc51aa14be9c4ad9f3d45f9dd2890776cfbccb55a (diff)
net: macb: match skb_reserve(skb, NET_IP_ALIGN) with HW alignment
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>
Diffstat (limited to 'drivers/net/ethernet/cadence/macb_main.c')
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 39673f5c3337..be3d0c2313a1 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -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,