Module Name: src Committed By: tsutsui Date: Sun May 31 05:10:47 UTC 2009
Modified Files: src/sys/dev/ic: rtl8169.c Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.120 -r1.121 src/sys/dev/ic/rtl8169.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/ic/rtl8169.c diff -u src/sys/dev/ic/rtl8169.c:1.120 src/sys/dev/ic/rtl8169.c:1.121 --- src/sys/dev/ic/rtl8169.c:1.120 Tue May 12 14:25:18 2009 +++ src/sys/dev/ic/rtl8169.c Sun May 31 05:10:47 2009 @@ -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 @@ 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) {