diff options
| author | Serge Semin <fancer.lancer@gmail.com> | 2025-05-29 15:46:33 +0300 |
|---|---|---|
| committer | Serge Semin <fancer.lancer@gmail.com> | 2026-08-13 20:31:12 +0300 |
| commit | 6c216f0f650ef304a36e8fe11e31fbefff758c39 (patch) | |
| tree | 10e1605c80830f3887c36905bf8ad28a122157d5 | |
| parent | e6e804c14a9638fab04f3dfb25732d7f02f35a31 (diff) | |
| download | linux-6c216f0f650ef304a36e8fe11e31fbefff758c39.tar.gz linux-6c216f0f650ef304a36e8fe11e31fbefff758c39.zip | |
net: stmmac: Discard Rx COE type 1 "support"
Here is what the DW GMAC databooks say about the Rx COE type 1 abilities:
"The application can enable IPv4 header checksum _checking_ and TCP/UDP
checksum _offload_ by setting the GMAC Configuration register’s IPC bit.
This module calculates the 16-bit ones’ complement of the Ethernet frame’s
payload data’s (DATA field) ones’ complement sum. ..." [1,2,3]
Basically it means that the engine _verifies_ the IPv4 header checksum
only and just calculates the 16-bit one's complement sum of the IPv4
datagrams for TCP/UDP protocols. The calculated value is just appended to
the frame pushed up to the system memory, which the driver just _ignores_.
The problem is that despite of all that the NETIF_F_RXCSUM feature is set
for Rx COE type 1 and the packets Rx procedure reports that the all the
IPv4 payloads csum is verified. It's definitely wrong.
In order to fix that let's just drop the entire Rx COE type 1 support
since it has never been properly handled in the driver anyway and most
importantly has been declared as legacy since DW GMAC v3.30a release [2,3]
claiming that the Type 2 engine is generally preferable. Regarding the
IPv4 header checking which is claimed to be performed by the type 1
engine, it's performed by the network core subsystem anyway.
Note originally, prior the commit 38912bdbde5f ("stmmac: sanitize the rx
coe and add the type-1 csum (v2)"), the driver had had the Rx COE type 2
support only [4]. So the implemented solution means to basically revert
the blamed commit provided never actually properly working change.
[1] DesignWare Cores Ethernet MAC Universal Databook, Revision 3.20a,
August 2003, p. 85.
[2] DesignWare Cores Ethernet MAC Universal Databook, Revision 3.50a,
February 2009, p. 114.
[3] DesignWare Cores Ethernet MAC Universal Databook, Revision 3.73a,
October 2013, p. 188.
[4] Link: https://lore.kernel.org/netdev/4F7A9D7E.8080007@st.com/
Fixes: 38912bdbde5f ("stmmac: sanitize the rx coe and add the type-1 csum (v2)")
Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/enh_desc.c | 14 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/hwif.h | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 15 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 20 | ||||
| -rw-r--r-- | include/linux/stmmac.h | 4 |
8 files changed, 13 insertions, 48 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index f06cc7013022..e2d467582698 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -1186,7 +1186,7 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) /* platform data specifying hardware features and callbacks. * hardware features were copied from Allwinner drivers. */ - plat_dat->rx_coe = STMMAC_RX_COE_TYPE2; + plat_dat->rx_coe = 1; plat_dat->tx_coe = 1; plat_dat->flags |= STMMAC_FLAG_HAS_SUN8I; plat_dat->bsp_priv = gmac; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c index 4a07dc1883f5..3ff30bc9f8c2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c @@ -210,7 +210,7 @@ static bool dwmac4_wrback_get_rx_vlan_valid(struct dma_desc *p) (le32_to_cpu(p->des3) & RDES3_RDES0_VALID)); } -static int dwmac4_wrback_get_rx_frame_len(struct dma_desc *p, int rx_coe) +static int dwmac4_wrback_get_rx_frame_len(struct dma_desc *p) { return (le32_to_cpu(p->des3) & RDES3_PACKET_SIZE_MASK); } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c index 7a32fc8018cf..029fbd24ded8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c @@ -155,7 +155,7 @@ static bool dwxgmac2_wrback_get_rx_vlan_valid(struct dma_desc *p) et_lt <= XGMAC_ET_LT_DVLAN_STAG_CTAG; } -static int dwxgmac2_get_rx_frame_len(struct dma_desc *p, int rx_coe) +static int dwxgmac2_get_rx_frame_len(struct dma_desc *p) { return (le32_to_cpu(p->des3) & XGMAC_RDES3_PL); } diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c index 1c3123d41ee9..0884fac85f29 100644 --- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c @@ -343,19 +343,9 @@ static void enh_desc_set_tx_ic(struct dma_desc *p) p->des0 |= cpu_to_le32(ETDES0_INTERRUPT); } -static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type) +static int enh_desc_get_rx_frame_len(struct dma_desc *p) { - unsigned int csum = 0; - /* The type-1 checksum offload engines append the checksum at - * the end of frame and the two bytes of checksum are added in - * the length. - * Adjust for that in the framelen for type-1 checksum offload - * engines. - */ - if (rx_coe_type == STMMAC_RX_COE_TYPE1) - csum = 2; - - return FIELD_GET(RDES0_FRAME_LEN_MASK, le32_to_cpu(p->des0)) - csum; + return FIELD_GET(RDES0_FRAME_LEN_MASK, le32_to_cpu(p->des0)); } static void enh_desc_enable_tx_timestamp(struct dma_desc *p) diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 39062c7f6778..8ee2f3fbef23 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -70,7 +70,7 @@ struct stmmac_desc_ops { /* Handle extra events on specific interrupts hw dependent */ void (*set_rx_owner)(struct dma_desc *p, int disable_rx_ic); /* Get the receive frame size */ - int (*get_rx_frame_len)(struct dma_desc *p, int rx_coe_type); + int (*get_rx_frame_len)(struct dma_desc *p); /* Return the reception status looking at the RDES1 */ int (*rx_status)(struct stmmac_extra_stats *x, struct dma_desc *p); diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c index eedb0efa43d0..4fdf75c6bab0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c @@ -205,20 +205,9 @@ static void ndesc_set_tx_ic(struct dma_desc *p) p->des1 |= cpu_to_le32(TDES1_INTERRUPT); } -static int ndesc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type) +static int ndesc_get_rx_frame_len(struct dma_desc *p) { - unsigned int csum = 0; - - /* The type-1 checksum offload engines append the checksum at - * the end of frame and the two bytes of checksum are added in - * the length. - * Adjust for that in the framelen for type-1 checksum offload - * engines - */ - if (rx_coe_type == STMMAC_RX_COE_TYPE1) - csum = 2; - - return FIELD_GET(RDES0_FRAME_LEN_MASK, le32_to_cpu(p->des0)) - csum; + return FIELD_GET(RDES0_FRAME_LEN_MASK, le32_to_cpu(p->des0)); } static void ndesc_enable_tx_timestamp(struct dma_desc *p) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 4471eab3692e..91aa8e9187ce 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -3719,7 +3719,7 @@ static int stmmac_hw_setup(struct net_device *dev) ret = stmmac_rx_ipc(priv, priv->hw); if (!ret) { netdev_warn(priv->dev, "RX IPC Checksum Offload disabled\n"); - priv->plat->rx_coe = STMMAC_RX_COE_NONE; + priv->plat->rx_coe = 0; priv->hw->rx_csum = 0; } @@ -5072,7 +5072,6 @@ static unsigned int stmmac_rx_buf1_len(struct stmmac_priv *priv, struct dma_desc *p, int status, unsigned int len) { - int coe = priv->hw->rx_csum; unsigned int plen = 0; /* Split header enabled */ @@ -5098,7 +5097,7 @@ 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, coe); + plen = stmmac_get_rx_frame_len(priv, p); /* First descriptor and last descriptor and not split header */ return min_t(unsigned int, priv->dma_conf.dma_buf_sz, plen); @@ -5108,7 +5107,6 @@ static unsigned int stmmac_rx_buf2_len(struct stmmac_priv *priv, struct dma_desc *p, int status, unsigned int len) { - int coe = priv->hw->rx_csum; unsigned int plen = 0; /* Not split header, buffer is not available */ @@ -5134,7 +5132,7 @@ static unsigned int stmmac_rx_buf2_len(struct stmmac_priv *priv, return priv->dma_conf.dma_buf_sz; /* GMAC4 or last descriptor */ - plen = stmmac_get_rx_frame_len(priv, p, coe); + plen = stmmac_get_rx_frame_len(priv, p); return plen - len; } @@ -6162,7 +6160,7 @@ static netdev_features_t stmmac_fix_features(struct net_device *dev, { struct stmmac_priv *priv = netdev_priv(dev); - if (priv->plat->rx_coe == STMMAC_RX_COE_NONE) + if (!priv->plat->rx_coe) features &= ~NETIF_F_RXCSUM; if (!priv->plat->tx_coe) @@ -7787,13 +7785,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv) else priv->plat->tx_coe = priv->dma_cap.tx_coe; - /* In case of GMAC4 rx_coe is from HW cap register. */ - priv->plat->rx_coe = priv->dma_cap.rx_coe; - - if (priv->dma_cap.rx_coe_type2) - priv->plat->rx_coe = STMMAC_RX_COE_TYPE2; - else if (priv->dma_cap.rx_coe_type1) - priv->plat->rx_coe = STMMAC_RX_COE_TYPE1; + priv->plat->rx_coe = priv->dma_cap.rx_coe || priv->dma_cap.rx_coe_type2; stmmac_print_actphyif(priv); } else { @@ -7803,8 +7795,6 @@ static int stmmac_hw_init(struct stmmac_priv *priv) if (priv->plat->rx_coe) { priv->hw->rx_csum = priv->plat->rx_coe; dev_info(priv->device, "RX Checksum Offload Engine supported\n"); - if (priv->synopsys_id < DWMAC_CORE_4_00) - dev_info(priv->device, "COE Type %d\n", priv->hw->rx_csum); } if (priv->plat->tx_coe) dev_info(priv->device, "TX Checksum insertion supported\n"); diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index b96bcb3905a7..934a536a3a0f 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -19,10 +19,6 @@ #define MTL_MAX_TX_QUEUES 8 #define STMMAC_CH_MAX 8 -#define STMMAC_RX_COE_NONE 0 -#define STMMAC_RX_COE_TYPE1 1 -#define STMMAC_RX_COE_TYPE2 2 - /* Define the macros for CSR clock range parameters to be passed by * platform code. * This could also be configured at run time using CPU freq framework. */ |
