summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerge Semin <fancer.lancer@gmail.com>2025-08-18 23:30:06 +0300
committerSerge Semin <fancer.lancer@gmail.com>2026-08-13 20:31:13 +0300
commit6573ddf62d8959787bd7323897decb84e503f9a4 (patch)
treef3d8c9927e9cc701c4fbc30ea167b6a559ea2cdd
parentc0a6524f98d39f6313d912130e4ebcd444f29d4a (diff)
downloadlinux-6573ddf62d8959787bd7323897decb84e503f9a4.tar.gz
linux-6573ddf62d8959787bd7323897decb84e503f9a4.zip
net: stmmac: Add RXFCS feature support
The HW-accelerated FCS/Pad stripping was removed in the commit 929d43421ee5 ("net: stmmac: Disable automatic FCS/Pad stripping"). Since then the FCS/Pad cutting of has been done by the driver itselft and for all incoming traffic. Due to that it will be quite easy to add the NETIF_F_RXFCS feature support - just convert the FCS stripping off code to being conditionally called. While at it move it out of the stmmac_rx()/stmmac_rx_zc() methods to the buffers length calculation functions to reduce the amount of the conditionals and to simplify the Rx methods. Also make sure the FCS trimming is applied to the very last Rx DMA-buffer. That is in case if Split Packet Header feature enabled and no header splitting happened both buffers can be utilized for the data reception. Thus the second buffer length must be trimmed of FCS field on that occasion. Of course the NETIF_F_RXALL feature will be disabled by default and will be enabled upon the user request. Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c54
1 files changed, 31 insertions, 23 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index fc585c562eba..f68ae9926689 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -5176,6 +5176,23 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
stmmac_enable_dma_reception(priv, priv->ioaddr, queue);
}
+/**
+ * stmmac_fcs_trimming - FCS field length
+ * @priv: driver private structure
+ * @status: frame Rx-status
+ * Description :
+ * Retrieve FCS length required to be trimmed of the Rx frame.
+ */
+static unsigned int stmmac_fcs_trimming(struct stmmac_priv *priv, int status)
+{
+ bool rxfcs = priv->dev->features & NETIF_F_RXFCS;
+
+ if (rxfcs)
+ return 0;
+
+ return ETH_FCS_LEN;
+}
+
static unsigned int stmmac_rx_buf1_len(struct stmmac_priv *priv,
struct dma_desc *p,
int status, unsigned int len)
@@ -5205,10 +5222,13 @@ static unsigned int stmmac_rx_buf1_len(struct stmmac_priv *priv,
return len ? plen : plen - stmmac_fs_offset();
}
- plen = stmmac_get_rx_frame_len(priv, p);
+ /* Last descriptor and not split header and secondary buffer used */
+ plen = stmmac_get_rx_frame_len(priv, p) - len;
+ if (plen > priv->dma_conf.dma_buf_sz)
+ return priv->dma_conf.dma_buf_sz;
- /* First descriptor and last descriptor and not split header */
- return min_t(unsigned int, priv->dma_conf.dma_buf_sz, plen);
+ /* Last descriptor and last buffer with FCS clipped of */
+ return plen - stmmac_fcs_trimming(priv, status);
}
static unsigned int stmmac_rx_buf2_len(struct stmmac_priv *priv,
@@ -5239,10 +5259,13 @@ static unsigned int stmmac_rx_buf2_len(struct stmmac_priv *priv,
if (priv->plat->core_type != DWMAC_CORE_GMAC4 && (status & rx_not_ls))
return priv->dma_conf.dma_buf_sz;
- /* GMAC4 or last descriptor */
- plen = stmmac_get_rx_frame_len(priv, p);
+ /* GMAC4 or last descriptor and secondary buffer unused */
+ plen = stmmac_get_rx_frame_len(priv, p) - len;
+ if (!plen)
+ return 0;
- return plen - len;
+ /* Last descriptor and last buffer with FCS clipped of */
+ return plen - stmmac_fcs_trimming(priv, status);
}
static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
@@ -5689,12 +5712,6 @@ read_again:
buf1_len = stmmac_rx_buf1_len(priv, p, status, len);
len += buf1_len;
- /* ACS is disabled; strip manually. */
- if (likely(!(status & rx_not_ls))) {
- buf1_len -= ETH_FCS_LEN;
- len -= ETH_FCS_LEN;
- }
-
/* RX buffer is good and fit into a XSK pool buffer */
buf->xdp->data_end = buf->xdp->data + buf1_len;
xsk_buff_dma_sync_for_cpu(buf->xdp);
@@ -5861,17 +5878,6 @@ read_again:
buf2_len = stmmac_rx_buf2_len(priv, p, status, len);
len += buf2_len;
- /* ACS is disabled; strip manually. */
- if (likely(!(status & rx_not_ls))) {
- if (buf2_len) {
- buf2_len -= ETH_FCS_LEN;
- len -= ETH_FCS_LEN;
- } else if (buf1_len) {
- buf1_len -= ETH_FCS_LEN;
- len -= ETH_FCS_LEN;
- }
- }
-
if (!skb) {
unsigned int pre_len, sync_len;
@@ -8425,6 +8431,8 @@ static int __stmmac_dvr_probe(struct device *device,
dwmac_is_xmac(priv->plat->core_type))
ndev->hw_features |= NETIF_F_RXALL;
+ ndev->hw_features |= NETIF_F_RXFCS;
+
ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
#ifdef STMMAC_VLAN_TAG_USED
/* Both mac100 and gmac support receive VLAN tag detection */