summaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/r8152.c
diff options
context:
space:
mode:
authorMark Lord2016-10-31 00:28:27 +0100
committerDavid S. Miller2016-10-31 01:56:13 +0100
commitb9a321b48af40e0606009df8aff0a8c65dfbbfd8 (patch)
tree699c9bd7cb3a48ab899db46f2e2a1c020604cb8b /drivers/net/usb/r8152.c
parentMerge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net (diff)
downloadkernel-qcow2-linux-b9a321b48af40e0606009df8aff0a8c65dfbbfd8.tar.gz
kernel-qcow2-linux-b9a321b48af40e0606009df8aff0a8c65dfbbfd8.tar.xz
kernel-qcow2-linux-b9a321b48af40e0606009df8aff0a8c65dfbbfd8.zip
r8152: Fix broken RX checksums.
The r8152 driver has been broken since (approx) 3.16.xx when support was added for hardware RX checksums on newer chip versions. Symptoms include random segfaults and silent data corruption over NFS. The hardware checksum logig does not work on the VER_02 dongles I have here when used with a slow embedded system CPU. Google reveals others reporting similar issues on Raspberry Pi. So, disable hardware RX checksum support for VER_02, and fix an obvious coding error for IPV6 checksums in the same function. Because this bug results in silent data corruption, it is a good candidate for back-porting to -stable >= 3.16.xx. Signed-off-by: Mark Lord <mlord@pobox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/usb/r8152.c')
-rw-r--r--drivers/net/usb/r8152.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 44d439f50961..75c516889645 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -1730,7 +1730,7 @@ static u8 r8152_rx_csum(struct r8152 *tp, struct rx_desc *rx_desc)
u8 checksum = CHECKSUM_NONE;
u32 opts2, opts3;
- if (tp->version == RTL_VER_01)
+ if (tp->version == RTL_VER_01 || tp->version == RTL_VER_02)
goto return_result;
opts2 = le32_to_cpu(rx_desc->opts2);
@@ -1745,7 +1745,7 @@ static u8 r8152_rx_csum(struct r8152 *tp, struct rx_desc *rx_desc)
checksum = CHECKSUM_NONE;
else
checksum = CHECKSUM_UNNECESSARY;
- } else if (RD_IPV6_CS) {
+ } else if (opts2 & RD_IPV6_CS) {
if ((opts2 & RD_UDP_CS) && !(opts3 & UDPF))
checksum = CHECKSUM_UNNECESSARY;
else if ((opts2 & RD_TCP_CS) && !(opts3 & TCPF))