diff options
| author | Serge Semin <fancer.lancer@gmail.com> | 2025-08-18 23:30:06 +0300 |
|---|---|---|
| committer | Serge Semin <fancer.lancer@gmail.com> | 2026-08-13 20:31:13 +0300 |
| commit | 6573ddf62d8959787bd7323897decb84e503f9a4 (patch) | |
| tree | f3d8c9927e9cc701c4fbc30ea167b6a559ea2cdd | |
| parent | c0a6524f98d39f6313d912130e4ebcd444f29d4a (diff) | |
| download | linux-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.c | 54 |
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 */ |
