]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: usb: lan78xx: fix silent drop of packets with checksum errors
authorOleksij Rempel <o.rempel@pengutronix.de>
Thu, 5 Mar 2026 14:34:26 +0000 (15:34 +0100)
committerJakub Kicinski <kuba@kernel.org>
Tue, 10 Mar 2026 02:48:33 +0000 (19:48 -0700)
Do not drop packets with checksum errors at the USB driver level;
pass them to the network stack.

Previously, the driver dropped all packets where the 'Receive Error
Detected' (RED) bit was set, regardless of the specific error type. This
caused packets with only IP or TCP/UDP checksum errors to be dropped
before reaching the kernel, preventing the network stack from accounting
for them or performing software fallback.

Add a mask for hard hardware errors to safely drop genuinely corrupt
frames, while allowing checksum-errored frames to pass with their
ip_summed field explicitly set to CHECKSUM_NONE.

Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver")
Cc: stable@vger.kernel.org
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Link: https://patch.msgid.link/20260305143429.530909-2-o.rempel@pengutronix.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/usb/lan78xx.c
drivers/net/usb/lan78xx.h

index a0021df12fde24bd9386cb4339f999b1d0b9b4c0..1c8f6919037881e3e1e656d083331e829f9a16a7 100644 (file)
@@ -3829,6 +3829,7 @@ static void lan78xx_rx_csum_offload(struct lan78xx_net *dev,
         */
        if (!(dev->net->features & NETIF_F_RXCSUM) ||
            unlikely(rx_cmd_a & RX_CMD_A_ICSM_) ||
+           unlikely(rx_cmd_a & RX_CMD_A_CSE_MASK_) ||
            ((rx_cmd_a & RX_CMD_A_FVTG_) &&
             !(dev->net->features & NETIF_F_HW_VLAN_CTAG_RX))) {
                skb->ip_summed = CHECKSUM_NONE;
@@ -3901,7 +3902,8 @@ static int lan78xx_rx(struct lan78xx_net *dev, struct sk_buff *skb,
                        return 0;
                }
 
-               if (unlikely(rx_cmd_a & RX_CMD_A_RED_)) {
+               if (unlikely(rx_cmd_a & RX_CMD_A_RED_) &&
+                   (rx_cmd_a & RX_CMD_A_RX_HARD_ERRS_MASK_)) {
                        netif_dbg(dev, rx_err, dev->net,
                                  "Error rx_cmd_a=0x%08x", rx_cmd_a);
                } else {
index 968e5e5faee0a7ce85662959a0c9f440bb289925..17a934acff3d649eec523eea1c96094eed517e26 100644 (file)
@@ -74,6 +74,9 @@
 #define RX_CMD_A_ICSM_                 (0x00004000)
 #define RX_CMD_A_LEN_MASK_             (0x00003FFF)
 
+#define RX_CMD_A_RX_HARD_ERRS_MASK_ \
+       (RX_CMD_A_RX_ERRS_MASK_ & ~RX_CMD_A_CSE_MASK_)
+
 /* Rx Command B */
 #define RX_CMD_B_CSUM_SHIFT_           (16)
 #define RX_CMD_B_CSUM_MASK_            (0xFFFF0000)