summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authortsutsui <tsutsui@NetBSD.org>2009-05-31 05:10:47 +0000
committertsutsui <tsutsui@NetBSD.org>2009-05-31 05:10:47 +0000
commita6363f7d5affe3246f6da9b1b0e85eadde6837e2 (patch)
tree887bb42ea3e21fd2785ce22140e488b87c0e5cf6 /sys/dev/ic
parent31a7ec7dc7b8d5de1f825fb4e7ba295075f2d5bf (diff)
Two fixes for RX hwcsum on DESCV2 chips:
* On checking TCPv4/UDPv4 RX checksum on DESCV2 chips, also check RE_RDESC_VLANCTL_IPV4 bit because those DESCV2 chips may also recognize IPv6 packets and set RE_PROTOID_TCPIP or RE_PROTOID_UDPIP bits for TCPv6/UDPv6 packets. This may fix PR kern/40605. * According to Realtek's Linux driver, DESCV2 chips don't set RE_PROTOID_IP for non-TCP/UDP IP packets (set only RE_RDESC_VLANCTL_IPV[46]) so remove PROTOID check for IPv4 RX cheksum on DESCV2 chips.
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/rtl8169.c66
1 files changed, 45 insertions, 21 deletions
diff --git a/sys/dev/ic/rtl8169.c b/sys/dev/ic/rtl8169.c
index ec6ab9057bf..7ba163263b9 100644
--- a/sys/dev/ic/rtl8169.c
+++ b/sys/dev/ic/rtl8169.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rtl8169.c,v 1.120 2009/05/12 14:25:18 cegger Exp $ */
+/* $NetBSD: rtl8169.c,v 1.121 2009/05/31 05:10:47 tsutsui Exp $ */
/*
* Copyright (c) 1997, 1998-2003
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rtl8169.c,v 1.120 2009/05/12 14:25:18 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rtl8169.c,v 1.121 2009/05/31 05:10:47 tsutsui Exp $");
/* $FreeBSD: /repoman/r/ncvs/src/sys/dev/re/if_re.c,v 1.20 2004/04/11 20:34:08 ru Exp $ */
/*
@@ -1251,25 +1251,49 @@ re_rxeof(struct rtk_softc *sc)
m->m_pkthdr.rcvif = ifp;
/* Do RX checksumming */
-
- /* Check IP header checksum */
- if ((rxstat & RE_RDESC_STAT_PROTOID) != 0 &&
- ((sc->sc_quirk & RTKQ_DESCV2) == 0 ||
- (rxvlan & RE_RDESC_VLANCTL_IPV4) != 0)) {
- m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
- if (rxstat & RE_RDESC_STAT_IPSUMBAD)
- m->m_pkthdr.csum_flags |= M_CSUM_IPv4_BAD;
- }
-
- /* Check TCP/UDP checksum */
- if (RE_TCPPKT(rxstat)) {
- m->m_pkthdr.csum_flags |= M_CSUM_TCPv4;
- if (rxstat & RE_RDESC_STAT_TCPSUMBAD)
- m->m_pkthdr.csum_flags |= M_CSUM_TCP_UDP_BAD;
- } else if (RE_UDPPKT(rxstat)) {
- m->m_pkthdr.csum_flags |= M_CSUM_UDPv4;
- if (rxstat & RE_RDESC_STAT_UDPSUMBAD)
- m->m_pkthdr.csum_flags |= M_CSUM_TCP_UDP_BAD;
+ if ((sc->sc_quirk & RTKQ_DESCV2) == 0) {
+ /* Check IP header checksum */
+ if ((rxstat & RE_RDESC_STAT_PROTOID) != 0) {
+ m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
+ if (rxstat & RE_RDESC_STAT_IPSUMBAD)
+ m->m_pkthdr.csum_flags |=
+ M_CSUM_IPv4_BAD;
+
+ /* Check TCP/UDP checksum */
+ if (RE_TCPPKT(rxstat)) {
+ m->m_pkthdr.csum_flags |= M_CSUM_TCPv4;
+ if (rxstat & RE_RDESC_STAT_TCPSUMBAD)
+ m->m_pkthdr.csum_flags |=
+ M_CSUM_TCP_UDP_BAD;
+ } else if (RE_UDPPKT(rxstat)) {
+ m->m_pkthdr.csum_flags |= M_CSUM_UDPv4;
+ if (rxstat & RE_RDESC_STAT_UDPSUMBAD)
+ m->m_pkthdr.csum_flags |=
+ M_CSUM_TCP_UDP_BAD;
+ }
+ }
+ } else {
+ /* Check IPv4 header checksum */
+ if ((rxvlan & RE_RDESC_VLANCTL_IPV4) != 0) {
+ m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
+ if (rxstat & RE_RDESC_STAT_IPSUMBAD)
+ m->m_pkthdr.csum_flags |=
+ M_CSUM_IPv4_BAD;
+
+ /* Check TCPv4/UDPv4 checksum */
+ if (RE_TCPPKT(rxstat)) {
+ m->m_pkthdr.csum_flags |= M_CSUM_TCPv4;
+ if (rxstat & RE_RDESC_STAT_TCPSUMBAD)
+ m->m_pkthdr.csum_flags |=
+ M_CSUM_TCP_UDP_BAD;
+ } else if (RE_UDPPKT(rxstat)) {
+ m->m_pkthdr.csum_flags |= M_CSUM_UDPv4;
+ if (rxstat & RE_RDESC_STAT_UDPSUMBAD)
+ m->m_pkthdr.csum_flags |=
+ M_CSUM_TCP_UDP_BAD;
+ }
+ }
+ /* XXX Check TCPv6/UDPv6 checksum? */
}
if (rxvlan & RE_RDESC_VLANCTL_TAG) {