summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerge Semin <fancer.lancer@gmail.com>2025-06-03 13:06:46 +0300
committerSerge Semin <fancer.lancer@gmail.com>2026-08-13 20:31:12 +0300
commitdf01b42941eda1c8a2d1685f6e986df5490af762 (patch)
treea38adc3c9c66ff9a947cf8f93f73c18fb01986e1
parent4b09925e77834b182aef2937871e0bf35df01a34 (diff)
downloadlinux-df01b42941eda1c8a2d1685f6e986df5490af762.tar.gz
linux-df01b42941eda1c8a2d1685f6e986df5490af762.zip
net: stmmac: dwmac4: Add csum Rx-descriptor status check
Currently the stmmac_desc_ops::rx_status() method always returns "Good frame" status for the IP-packets with erroneous checksum. Here is what DW QoS Eth databook says about the Rx COE flags in the Rx DMA-descriptor: "RDES0.IPCE IP Payload Error ... Bit 15 (ES) of RDES3 is not set when this bit is set." [1] Thus the "Discard frame" status won't be returned from the stmmac_desc_ops::rx_status() method for the frames failed to pass the control-sum check. Instead such packets will be passed to the upper software layers with the "checksum unnecessary" status, which makes the upper layer being unaware of the packets inconsistency. This is definitely a bug. Moreover the "Good frame" is returned for the unverified frames too (unsupported by the Rx Checksum Offload engine). This isn't that much problematic as the bug but generally speaking this is also incorrect because it doesn't give an opportunity for the upper software layer to detect the IP csum status for sure. Instead the STMMAC core driver has to implement an heuristic method like stmmac_has_ip_ethertype() which is not only incomplete but also causes a false-positive CSUM verification status passed up to the networking core. Let's fix all of the problems above in the DW QoS Eth (GMAC4+) as a preparation before a complete fix of the commit c2945c435c99 ("net: stmmac: Prevent DSA tags from breaking COE") is provided. Fixes: 753a71090f33 ("stmmac: add descriptors function for GMAC 4.xx") Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
index 3ff30bc9f8c2..2c741bdae6fa 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
@@ -106,18 +106,22 @@ static int dwmac4_wrback_get_rx_status(struct stmmac_extra_stats *x,
if (rdes1 & RDES1_IP_HDR_ERROR) {
x->ip_hdr_err++;
- ret |= csum_none;
+ ret = discard_frame;
+ }
+ if (rdes1 & RDES1_IP_PAYLOAD_ERROR) {
+ x->ip_payload_err++;
+ ret = discard_frame;
}
- if (rdes1 & RDES1_IP_CSUM_BYPASSED)
+ if (rdes1 & RDES1_IP_CSUM_BYPASSED) {
x->ip_csum_bypassed++;
+ ret |= csum_none;
+ }
if (rdes1 & RDES1_IPV4_HEADER)
x->ipv4_pkt_rcvd++;
- if (rdes1 & RDES1_IPV6_HEADER)
+ else if (rdes1 & RDES1_IPV6_HEADER)
x->ipv6_pkt_rcvd++;
- if (rdes1 & RDES1_IP_PAYLOAD_ERROR) {
- x->ip_payload_err++;
+ else /* Not an IP packet or COE is disabled */
ret |= csum_none;
- }
if (message_type == RDES_EXT_NO_PTP)
x->no_ptp_rx_msg_type_ext++;