diff options
| author | tsutsui <tsutsui@NetBSD.org> | 2009-05-31 05:10:47 +0000 |
|---|---|---|
| committer | tsutsui <tsutsui@NetBSD.org> | 2009-05-31 05:10:47 +0000 |
| commit | a6363f7d5affe3246f6da9b1b0e85eadde6837e2 (patch) | |
| tree | 887bb42ea3e21fd2785ce22140e488b87c0e5cf6 /sys/dev/ic | |
| parent | 31a7ec7dc7b8d5de1f825fb4e7ba295075f2d5bf (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.c | 66 |
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) { |
